source: mainline/uspace/app/init/init.c@ 1c635d6

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 1c635d6 was 1c635d6, checked in by Martin Sucha <sucha14@…>, 11 years ago

Do not hold a task's return value after it has disconnected.

Holding the task's return value meant that if nobody waited
for task's result, it polluted NS's memory. This was apparently
done because of a race between spawning a task and waiting for it.

We solve this problem in another way: ns discards the return value
as soon as the task disconnects from it. This typically happens
when the task finishes its execution. In order to avoid the race,
we send the wait request to ns while spawning the task (i.e. when
we talk to the loader), but before we allow the loaded program
to run.

Fixes #132

  • Property mode set to 100644
File size: 9.3 KB
Line 
1/*
2 * Copyright (c) 2005 Martin Decky
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/** @addtogroup init Init
30 * @brief Init process for user space environment configuration.
31 * @{
32 */
33/**
34 * @file
35 */
36
37#include <stdio.h>
38#include <unistd.h>
39#include <stdarg.h>
40#include <vfs/vfs.h>
41#include <stdbool.h>
42#include <errno.h>
43#include <fcntl.h>
44#include <sys/stat.h>
45#include <task.h>
46#include <malloc.h>
47#include <macros.h>
48#include <str.h>
49#include <loc.h>
50#include <str_error.h>
51#include "init.h"
52
53#define ROOT_DEVICE "bd/initrd"
54#define ROOT_MOUNT_POINT "/"
55
56#define LOCFS_FS_TYPE "locfs"
57#define LOCFS_MOUNT_POINT "/loc"
58
59#define TMPFS_FS_TYPE "tmpfs"
60#define TMPFS_MOUNT_POINT "/tmp"
61
62#define SRV_CONSOLE "/srv/console"
63#define APP_GETTERM "/app/getterm"
64
65#define SRV_COMPOSITOR "/srv/compositor"
66
67#define HID_INPUT "hid/input"
68#define HID_OUTPUT "hid/output"
69#define HID_COMPOSITOR_SERVER ":0"
70
71#define srv_start(path, ...) \
72 srv_startl(path, path, ##__VA_ARGS__, NULL)
73
74/** Print banner */
75static void info_print(void)
76{
77 printf("%s: HelenOS init\n", NAME);
78}
79
80/** Report mount operation success */
81static bool mount_report(const char *desc, const char *mntpt,
82 const char *fstype, const char *dev, int rc)
83{
84 switch (rc) {
85 case EOK:
86 if (dev != NULL)
87 printf("%s: %s mounted on %s (%s at %s)\n", NAME, desc, mntpt,
88 fstype, dev);
89 else
90 printf("%s: %s mounted on %s (%s)\n", NAME, desc, mntpt, fstype);
91 break;
92 case EBUSY:
93 printf("%s: %s already mounted on %s\n", NAME, desc, mntpt);
94 return false;
95 case ELIMIT:
96 printf("%s: %s limit exceeded\n", NAME, desc);
97 return false;
98 case ENOENT:
99 printf("%s: %s unknown type (%s)\n", NAME, desc, fstype);
100 return false;
101 default:
102 printf("%s: %s not mounted on %s (%s)\n", NAME, desc, mntpt,
103 str_error(rc));
104 return false;
105 }
106
107 return true;
108}
109
110/** Mount root filesystem
111 *
112 * The operation blocks until the root filesystem
113 * server is ready for mounting.
114 *
115 * @param[in] fstype Root filesystem type.
116 *
117 * @return True on success.
118 * @return False on failure.
119 *
120 */
121static bool mount_root(const char *fstype)
122{
123 const char *opts = "";
124
125 if (str_cmp(fstype, "tmpfs") == 0)
126 opts = "restore";
127
128 int rc = mount(fstype, ROOT_MOUNT_POINT, ROOT_DEVICE, opts,
129 IPC_FLAG_BLOCKING, 0);
130 return mount_report("Root filesystem", ROOT_MOUNT_POINT, fstype,
131 ROOT_DEVICE, rc);
132}
133
134/** Mount locfs filesystem
135 *
136 * The operation blocks until the locfs filesystem
137 * server is ready for mounting.
138 *
139 * @return True on success.
140 * @return False on failure.
141 *
142 */
143static bool mount_locfs(void)
144{
145 int rc = mount(LOCFS_FS_TYPE, LOCFS_MOUNT_POINT, "", "",
146 IPC_FLAG_BLOCKING, 0);
147 return mount_report("Location service filesystem", LOCFS_MOUNT_POINT,
148 LOCFS_FS_TYPE, NULL, rc);
149}
150
151static int srv_startl(const char *path, ...)
152{
153 struct stat s;
154 if (stat(path, &s) == ENOENT) {
155 printf("%s: Unable to stat %s\n", NAME, path);
156 return ENOENT;
157 }
158
159 printf("%s: Starting %s\n", NAME, path);
160
161 va_list ap;
162 const char *arg;
163 int cnt = 0;
164
165 va_start(ap, path);
166 do {
167 arg = va_arg(ap, const char *);
168 cnt++;
169 } while (arg != NULL);
170 va_end(ap);
171
172 va_start(ap, path);
173 task_id_t id;
174 task_wait_t wait;
175 int rc = task_spawn(&id, &wait, path, cnt, ap);
176 va_end(ap);
177
178 if (rc != EOK) {
179 printf("%s: Error spawning %s (%s)\n", NAME, path,
180 str_error(rc));
181 return rc;
182 }
183
184 if (!id) {
185 printf("%s: Error spawning %s (invalid task id)\n", NAME,
186 path);
187 return EINVAL;
188 }
189
190 task_exit_t texit;
191 int retval;
192 rc = task_wait(&wait, &texit, &retval);
193 if (rc != EOK) {
194 printf("%s: Error waiting for %s (%s)\n", NAME, path,
195 str_error(rc));
196 return rc;
197 }
198
199 if (texit != TASK_EXIT_NORMAL) {
200 printf("%s: Server %s failed to start (unexpectedly "
201 "terminated)\n", NAME, path);
202 return EINVAL;
203 }
204
205 if (retval != 0)
206 printf("%s: Server %s failed to start (exit code %d)\n", NAME,
207 path, retval);
208
209 return retval;
210}
211
212static int console(const char *isvc, const char *osvc)
213{
214 /* Wait for the input service to be ready */
215 service_id_t service_id;
216 int rc = loc_service_get_id(isvc, &service_id, IPC_FLAG_BLOCKING);
217 if (rc != EOK) {
218 printf("%s: Error waiting on %s (%s)\n", NAME, isvc,
219 str_error(rc));
220 return rc;
221 }
222
223 /* Wait for the output service to be ready */
224 rc = loc_service_get_id(osvc, &service_id, IPC_FLAG_BLOCKING);
225 if (rc != EOK) {
226 printf("%s: Error waiting on %s (%s)\n", NAME, osvc,
227 str_error(rc));
228 return rc;
229 }
230
231 return srv_start(SRV_CONSOLE, isvc, osvc);
232}
233
234static int compositor(const char *isvc, const char *name)
235{
236 /* Wait for the input service to be ready */
237 service_id_t service_id;
238 int rc = loc_service_get_id(isvc, &service_id, IPC_FLAG_BLOCKING);
239 if (rc != EOK) {
240 printf("%s: Error waiting on %s (%s)\n", NAME, isvc,
241 str_error(rc));
242 return rc;
243 }
244
245 return srv_start(SRV_COMPOSITOR, isvc, name);
246}
247
248static int gui_start(const char *app, const char *srv_name)
249{
250 char winreg[50];
251 snprintf(winreg, sizeof(winreg), "%s%s%s", "comp", srv_name, "/winreg");
252
253 printf("%s: Spawning %s %s\n", NAME, app, winreg);
254
255 task_id_t id;
256 task_wait_t wait;
257 int rc = task_spawnl(&id, &wait, app, app, winreg, NULL);
258 if (rc != EOK) {
259 printf("%s: Error spawning %s %s (%s)\n", NAME, app,
260 winreg, str_error(rc));
261 return -1;
262 }
263
264 task_exit_t texit;
265 int retval;
266 rc = task_wait(&wait, &texit, &retval);
267 if ((rc != EOK) || (texit != TASK_EXIT_NORMAL)) {
268 printf("%s: Error retrieving retval from %s (%s)\n", NAME,
269 app, str_error(rc));
270 return -1;
271 }
272
273 return retval;
274}
275
276static void getterm(const char *svc, const char *app, bool msg)
277{
278 if (msg) {
279 printf("%s: Spawning %s %s %s --msg --wait -- %s\n", NAME,
280 APP_GETTERM, svc, LOCFS_MOUNT_POINT, app);
281
282 int rc = task_spawnl(NULL, NULL, APP_GETTERM, APP_GETTERM, svc,
283 LOCFS_MOUNT_POINT, "--msg", "--wait", "--", app, NULL);
284 if (rc != EOK)
285 printf("%s: Error spawning %s %s %s --msg --wait -- %s\n",
286 NAME, APP_GETTERM, svc, LOCFS_MOUNT_POINT, app);
287 } else {
288 printf("%s: Spawning %s %s %s --wait -- %s\n", NAME,
289 APP_GETTERM, svc, LOCFS_MOUNT_POINT, app);
290
291 int rc = task_spawnl(NULL, NULL, APP_GETTERM, APP_GETTERM, svc,
292 LOCFS_MOUNT_POINT, "--wait", "--", app, NULL);
293 if (rc != EOK)
294 printf("%s: Error spawning %s %s %s --wait -- %s\n",
295 NAME, APP_GETTERM, svc, LOCFS_MOUNT_POINT, app);
296 }
297}
298
299static bool mount_tmpfs(void)
300{
301 int rc = mount(TMPFS_FS_TYPE, TMPFS_MOUNT_POINT, "", "", 0, 0);
302 return mount_report("Temporary filesystem", TMPFS_MOUNT_POINT,
303 TMPFS_FS_TYPE, NULL, rc);
304}
305
306int main(int argc, char *argv[])
307{
308 info_print();
309
310 if (!mount_root(STRING(RDFMT))) {
311 printf("%s: Exiting\n", NAME);
312 return 1;
313 }
314
315 /* Make sure tmpfs is running. */
316 if (str_cmp(STRING(RDFMT), "tmpfs") != 0)
317 srv_start("/srv/tmpfs");
318
319 srv_start("/srv/klog");
320 srv_start("/srv/locfs");
321 srv_start("/srv/taskmon");
322
323 if (!mount_locfs()) {
324 printf("%s: Exiting\n", NAME);
325 return 2;
326 }
327
328 mount_tmpfs();
329
330 srv_start("/srv/devman");
331 srv_start("/srv/apic");
332 srv_start("/srv/i8259");
333 srv_start("/srv/obio");
334 srv_start("/srv/cuda_adb");
335 srv_start("/srv/s3c24xx_uart");
336 srv_start("/srv/s3c24xx_ts");
337
338 srv_start("/srv/loopip");
339 srv_start("/srv/ethip");
340 srv_start("/srv/inetsrv");
341 srv_start("/srv/tcp");
342 srv_start("/srv/udp");
343 srv_start("/srv/dnsrsrv");
344 srv_start("/srv/dhcp");
345 srv_start("/srv/nconfsrv");
346
347 srv_start("/srv/clipboard");
348 srv_start("/srv/remcons");
349
350 srv_start("/srv/input", HID_INPUT);
351 srv_start("/srv/output", HID_OUTPUT);
352 srv_start("/srv/hound");
353
354 int rc = compositor(HID_INPUT, HID_COMPOSITOR_SERVER);
355 if (rc == EOK) {
356 gui_start("/app/vlaunch", HID_COMPOSITOR_SERVER);
357 gui_start("/app/vterm", HID_COMPOSITOR_SERVER);
358 }
359
360 rc = console(HID_INPUT, HID_OUTPUT);
361 if (rc == EOK) {
362 getterm("term/vc0", "/app/bdsh", true);
363 getterm("term/vc1", "/app/bdsh", false);
364 getterm("term/vc2", "/app/bdsh", false);
365 getterm("term/vc3", "/app/bdsh", false);
366 getterm("term/vc4", "/app/bdsh", false);
367 getterm("term/vc5", "/app/bdsh", false);
368 }
369
370 return 0;
371}
372
373/** @}
374 */
Note: See TracBrowser for help on using the repository browser.