source: mainline/uspace/srv/sysman/sm_task.c@ c7b9db03

Last change on this file since c7b9db03 was c7b9db03, checked in by Matthieu Riolo <matthieu.riolo@…>, 6 years ago

sysman: Workaround for graphical applications as services

  • Property mode set to 100644
File size: 5.3 KB
Line 
1/*
2 * Copyright (c) 2015 Michal Koutny
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <adt/list.h>
30#include <errno.h>
31#include <stdlib.h>
32#include <task.h>
33#include <sysman/unit.h>
34
35#include "repo.h"
36#include "log.h"
37#include "sysman.h"
38#include "sm_task.h"
39
40
41/** Structure for boxing task event */
42struct sm_task_event {
43 task_id_t task_id;
44 int flags;
45 task_exit_t texit;
46 int retval;
47};
48
49static void sysman_event_task_event(void *);
50
51/**
52 * @note This function runs in separate fibril (not same as event loop).
53 */
54static void sm_task_event_handler(task_id_t tid, int flags, task_exit_t texit,
55 int retval)
56{
57 sm_task_event_t *tev = malloc(sizeof(sm_task_event_t));
58 if (tev == NULL) {
59 sysman_log(LVL_FATAL,
60 "Unable to process event of task %" PRIu64 ".", tid);
61 return;
62 }
63 tev->task_id = tid;
64 tev->flags = flags;
65 tev->texit = texit;
66 tev->retval = retval;
67
68 sysman_raise_event(&sysman_event_task_event, tev);
69}
70
71static unit_svc_t *sm_task_find_service(task_id_t tid)
72{
73 /*
74 * Unit to task is about to be developed, so use plain linear search
75 * instead of specialized structures.
76 */
77 list_foreach(units, units, unit_t, u) {
78 if (u->type != UNIT_SERVICE) {
79 continue;
80 }
81 if (CAST_SVC(u)->main_task_id == tid) {
82 return CAST_SVC(u);
83 }
84
85 }
86
87 return NULL;
88}
89
90static unit_svc_t *sm_task_create_service(task_id_t tid)
91{
92 unit_t *u_svc = unit_create(UNIT_SERVICE);
93 bool in_repo_update = false;
94 int rc = EOK;
95
96 if (u_svc == NULL) {
97 goto fail;
98 }
99
100 rc = asprintf(&u_svc->name, ANONYMOUS_SERVICE_MASK "%c%s", tid,
101 UNIT_NAME_SEPARATOR, UNIT_SVC_TYPE_NAME);
102 if (rc < 0) {
103 goto fail;
104 }
105
106 CAST_SVC(u_svc)->main_task_id = tid;
107 CAST_SVC(u_svc)->anonymous = true;
108 /* exec_start is left undefined, maybe could be hinted by kernel's task
109 * name */
110
111 repo_begin_update();
112 in_repo_update = true;
113
114 rc = repo_add_unit(u_svc);
115 if (rc != EOK) {
116 goto fail;
117 }
118
119 repo_commit();
120
121 return CAST_SVC(u_svc);
122
123fail:
124 if (in_repo_update) {
125 repo_rollback();
126 }
127
128 unit_destroy(&u_svc);
129 return NULL;
130}
131
132static void sm_task_delete_service(unit_svc_t *u_svc)
133{
134 repo_begin_update();
135 int rc = repo_remove_unit(&u_svc->unit);
136 if (rc != EOK) {
137 sysman_log(LVL_WARN, "Can't remove unit %s (%i).",
138 unit_name(&u_svc->unit), rc);
139 repo_rollback();
140 return;
141 }
142
143 repo_commit();
144}
145
146static void sysman_event_task_event(void *data)
147{
148 sm_task_event_t *tev = data;
149
150 sysman_log(LVL_DEBUG2, "%s, %" PRIu64 " %i",
151 __func__, tev->task_id, tev->flags);
152 unit_svc_t *u_svc = sm_task_find_service(tev->task_id);
153
154 if (u_svc == NULL) {
155 if (tev->flags & TASK_WAIT_EXIT) {
156 /* Non-service task exited, ignore. */
157 goto finish;
158 }
159
160 u_svc = sm_task_create_service(tev->task_id);
161 if (u_svc == NULL) {
162 sysman_log(LVL_WARN,
163 "Unable to create anonymous service for task %" PRIu64 ".",
164 tev->task_id);
165 goto finish;
166 }
167
168 sysman_log(LVL_DEBUG, "Created anonymous service %s.",
169 unit_name(&u_svc->unit));
170
171 /* Inject state so that further processing makes sense */
172 u_svc->unit.state = STATE_STARTING;
173 }
174
175
176 /* Simple incomplete state automaton */
177 unit_t *u = &u_svc->unit;
178 sysman_log(LVL_DEBUG2, "%s, %s(%i)@%" PRIu64 " %i",
179 __func__, unit_name(u), u->state, tev->task_id, tev->flags);
180
181 if (tev->flags & TASK_WAIT_EXIT) {
182 // TODO maybe call unit_fail (would be nice to contain reason)
183 // or move this whole logic to unit_svc.c
184 if (u->state == STATE_STOPPING) {
185 u->state = STATE_STOPPED;
186 } else {
187 // if it has also retval == 0 then it's not fail
188 u->state = STATE_FAILED;
189 }
190
191 } else if (tev->flags & TASK_WAIT_RETVAL) {
192 assert(u->state == STATE_STARTING);
193 u->state = STATE_STARTED;
194 }
195
196 unit_notify_state(u);
197
198 if ((tev->flags & TASK_WAIT_EXIT) && u_svc->anonymous) {
199 sysman_log(LVL_DEBUG, "Deleted anonymous service %s.",
200 unit_name(&u_svc->unit));
201 sm_task_delete_service(u_svc);
202 }
203finish:
204 free(tev);
205}
206
207int sm_task_start(void)
208{
209 int rc = task_register_event_handler(&sm_task_event_handler, true);
210 return rc;
211}
Note: See TracBrowser for help on using the repository browser.