source: mainline/uspace/app/bdsh/exec.c@ 1ede059

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 1ede059 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: 4.1 KB
Line 
1/*
2 * Copyright (c) 2008 Tim Post
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/* The VERY basics of execute in place support. These are buggy, leaky
30 * and not nearly done. Only here for beta testing!! You were warned!!
31 * TODO:
32 * Hash command lookups to save time
33 * Create a running pointer to **path and advance/rewind it as we go */
34
35#include <stdio.h>
36#include <stdlib.h>
37#include <unistd.h>
38#include <str.h>
39#include <fcntl.h>
40#include <str_error.h>
41#include <errno.h>
42#include <vfs/vfs.h>
43
44#include "config.h"
45#include "util.h"
46#include "exec.h"
47#include "errors.h"
48
49/* FIXME: Just have find_command() return an allocated string */
50static char *found;
51
52static char *find_command(char *);
53static int try_access(const char *);
54
55const char *search_dir[] = { "/app", "/srv", NULL };
56
57/* work-around for access() */
58static int try_access(const char *f)
59{
60 int fd;
61
62 fd = open(f, O_RDONLY);
63 if (fd > -1) {
64 close(fd);
65 return 0;
66 } else
67 return -1;
68}
69
70/* Returns the full path of "cmd" if cmd is found, else just hand back
71 * cmd as it was presented */
72static char *find_command(char *cmd)
73{
74 size_t i;
75
76 found = (char *)malloc(PATH_MAX);
77
78 /* The user has specified a full or relative path, just give it back. */
79 if (-1 != try_access(cmd)) {
80 return (char *) cmd;
81 }
82
83 /* We now have n places to look for the command */
84 for (i = 0; search_dir[i] != NULL; i++) {
85 memset(found, 0, PATH_MAX);
86 snprintf(found, PATH_MAX, "%s/%s", search_dir[i], cmd);
87 if (-1 != try_access(found)) {
88 return (char *) found;
89 }
90 }
91
92 /* We didn't find it, just give it back as-is. */
93 return (char *) cmd;
94}
95
96unsigned int try_exec(char *cmd, char **argv, iostate_t *io)
97{
98 task_id_t tid;
99 task_wait_t twait;
100 task_exit_t texit;
101 char *tmp;
102 int rc, retval, i;
103 int file_handles[3];
104 int *file_handles_p[4];
105 FILE *files[3];
106
107 tmp = str_dup(find_command(cmd));
108 free(found);
109
110 files[0] = io->stdin;
111 files[1] = io->stdout;
112 files[2] = io->stderr;
113
114 for (i = 0; i < 3 && files[i] != NULL; i++) {
115 if (fhandle(files[i], &file_handles[i]) == EOK) {
116 file_handles_p[i] = &file_handles[i];
117 }
118 else {
119 file_handles_p[i] = NULL;
120 }
121 }
122 file_handles_p[i] = NULL;
123
124 rc = task_spawnvf(&tid, &twait, tmp, (const char **) argv, file_handles_p);
125 free(tmp);
126
127 if (rc != 0) {
128 cli_error(CL_EEXEC, "%s: Cannot spawn `%s' (%s)", progname, cmd,
129 str_error(rc));
130 return 1;
131 }
132
133 rc = task_wait(&twait, &texit, &retval);
134 if (rc != EOK) {
135 printf("%s: Failed waiting for command (%s)\n", progname,
136 str_error(rc));
137 return 1;
138 } else if (texit != TASK_EXIT_NORMAL) {
139 printf("%s: Command failed (unexpectedly terminated)\n", progname);
140 return 1;
141 } else if (retval != 0) {
142 printf("%s: Command failed (exit code %d)\n",
143 progname, retval);
144 return 1;
145 }
146
147 return 0;
148}
Note: See TracBrowser for help on using the repository browser.