OLD | NEW |
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include <errno.h> | 5 #include <errno.h> |
6 #include <fcntl.h> | 6 #include <fcntl.h> |
7 #include <signal.h> | 7 #include <signal.h> |
8 #include <stdio.h> | 8 #include <stdio.h> |
9 #include <stdlib.h> | 9 #include <stdlib.h> |
10 #include <string.h> | 10 #include <string.h> |
11 #include <unistd.h> | 11 #include <unistd.h> |
12 | 12 |
13 #include "bin/fdutils.h" | 13 #include "bin/fdutils.h" |
14 #include "bin/process.h" | 14 #include "bin/process.h" |
15 #include "bin/set.h" | |
16 | 15 |
17 | 16 |
18 class ActiveProcess { | 17 class ProcessInfo { |
19 public: | 18 public: |
20 pid_t pid; | 19 ProcessInfo(pid_t pid, intptr_t fd) : pid_(pid), fd_(fd) { } |
21 intptr_t fd; | |
22 | 20 |
23 bool operator==(const ActiveProcess &other) const { | 21 pid_t pid() { return pid_; } |
24 if (pid == other.pid) { | 22 intptr_t fd() { return fd_; } |
25 return true; | 23 ProcessInfo* next() { return next_; } |
26 } | 24 void set_next(ProcessInfo* next) { next_ = next; } |
27 return false; | 25 |
28 } | 26 private: |
| 27 pid_t pid_; // Process pid. |
| 28 intptr_t fd_; // File descriptor for pipe to report exit code. |
| 29 ProcessInfo* next_; |
29 }; | 30 }; |
30 | 31 |
31 | 32 |
32 static Set<ActiveProcess> activeProcesses; | 33 ProcessInfo* active_processes = NULL; |
| 34 |
| 35 |
| 36 static void AddProcess(ProcessInfo* process) { |
| 37 process->set_next(active_processes); |
| 38 active_processes = process; |
| 39 } |
| 40 |
| 41 |
| 42 static ProcessInfo* LookupProcess(pid_t pid) { |
| 43 ProcessInfo* current = active_processes; |
| 44 while (current != NULL) { |
| 45 if (current->pid() == pid) { |
| 46 return current; |
| 47 } |
| 48 current = current->next(); |
| 49 } |
| 50 return NULL; |
| 51 } |
| 52 |
| 53 |
| 54 static void RemoveProcess(pid_t pid) { |
| 55 ProcessInfo* prev = NULL; |
| 56 ProcessInfo* current = active_processes; |
| 57 while (current != NULL) { |
| 58 if (current->pid() == pid) { |
| 59 if (prev == NULL) { |
| 60 active_processes = current->next(); |
| 61 } else { |
| 62 prev->set_next(current->next()); |
| 63 } |
| 64 delete current; |
| 65 return; |
| 66 } |
| 67 prev = current; |
| 68 current = current->next(); |
| 69 } |
| 70 } |
33 | 71 |
34 | 72 |
35 static char* SafeStrNCpy(char* dest, const char* src, size_t n) { | 73 static char* SafeStrNCpy(char* dest, const char* src, size_t n) { |
36 strncpy(dest, src, n); | 74 strncpy(dest, src, n); |
37 dest[n - 1] = '\0'; | 75 dest[n - 1] = '\0'; |
38 return dest; | 76 return dest; |
39 } | 77 } |
40 | 78 |
41 | 79 |
42 static void SetChildOsErrorMessage(char* os_error_message, | 80 static void SetChildOsErrorMessage(char* os_error_message, |
43 int os_error_message_len) { | 81 int os_error_message_len) { |
44 SafeStrNCpy(os_error_message, strerror(errno), os_error_message_len); | 82 SafeStrNCpy(os_error_message, strerror(errno), os_error_message_len); |
45 } | 83 } |
46 | 84 |
47 | 85 |
48 void ExitHandle(int processSignal, siginfo_t* siginfo, void* tmp) { | 86 void ExitHandler(int process_signal, siginfo_t* siginfo, void* tmp) { |
49 assert(processSignal == SIGCHLD); | 87 assert(process_signal == SIGCHLD); |
50 struct sigaction act; | 88 struct sigaction act; |
51 bzero(&act, sizeof(act)); | 89 bzero(&act, sizeof(act)); |
52 act.sa_handler = SIG_IGN; | 90 act.sa_handler = SIG_IGN; |
53 act.sa_flags = SA_NOCLDSTOP | SA_SIGINFO; | 91 act.sa_flags = SA_NOCLDSTOP | SA_SIGINFO; |
54 if (sigaction(SIGCHLD, &act, 0) != 0) { | 92 if (sigaction(SIGCHLD, &act, 0) != 0) { |
55 perror("Process start: disabling signal handler failed"); | 93 perror("Process start: disabling signal handler failed"); |
56 } | 94 } |
57 pid_t pid = siginfo->si_pid; | 95 ProcessInfo* process = LookupProcess(siginfo->si_pid); |
58 ActiveProcess element; | 96 if (process != NULL) { |
59 element.pid = pid; | 97 intptr_t message[2] = { siginfo->si_pid, siginfo->si_status }; |
60 ActiveProcess* current = activeProcesses.Remove(element); | |
61 if (current != NULL) { | |
62 intptr_t message = siginfo->si_status; | |
63 intptr_t result = | 98 intptr_t result = |
64 FDUtils::WriteToBlocking(current->fd, &message, sizeof(message)); | 99 FDUtils::WriteToBlocking(process->fd(), &message, sizeof(message)); |
65 if (result != sizeof(message)) { | 100 if (result != sizeof(message)) { |
66 perror("ExitHandle notification failed"); | 101 perror("ExitHandler notification failed"); |
67 } | 102 } |
68 close(current->fd); | 103 close(process->fd()); |
69 | |
70 delete current; | |
71 } | 104 } |
72 act.sa_handler = 0; | 105 act.sa_handler = 0; |
73 act.sa_sigaction = ExitHandle; | 106 act.sa_sigaction = ExitHandler; |
74 if (sigaction(SIGCHLD, &act, 0) != 0) { | 107 if (sigaction(SIGCHLD, &act, 0) != 0) { |
75 perror("Process start: enabling signal handler failed"); | 108 perror("Process start: enabling signal handler failed"); |
76 } | 109 } |
77 } | 110 } |
78 | 111 |
79 | 112 |
80 int Process::Start(const char* path, | 113 int Process::Start(const char* path, |
81 char* arguments[], | 114 char* arguments[], |
82 intptr_t arguments_length, | 115 intptr_t arguments_length, |
83 intptr_t* in, | 116 intptr_t* in, |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
153 | 186 |
154 char* program_arguments[arguments_length + 2]; | 187 char* program_arguments[arguments_length + 2]; |
155 program_arguments[0] = const_cast<char *>(path); | 188 program_arguments[0] = const_cast<char *>(path); |
156 for (int i = 0; i < arguments_length; i++) { | 189 for (int i = 0; i < arguments_length; i++) { |
157 program_arguments[i + 1] = arguments[i]; | 190 program_arguments[i + 1] = arguments[i]; |
158 } | 191 } |
159 program_arguments[arguments_length + 1] = NULL; | 192 program_arguments[arguments_length + 1] = NULL; |
160 | 193 |
161 struct sigaction act; | 194 struct sigaction act; |
162 bzero(&act, sizeof(act)); | 195 bzero(&act, sizeof(act)); |
163 act.sa_sigaction = ExitHandle; | 196 act.sa_sigaction = ExitHandler; |
164 act.sa_flags = SA_NOCLDSTOP | SA_SIGINFO; | 197 act.sa_flags = SA_NOCLDSTOP | SA_SIGINFO; |
165 if (sigaction(SIGCHLD, &act, 0) != 0) { | 198 if (sigaction(SIGCHLD, &act, 0) != 0) { |
166 perror("Process start: setting signal handler failed"); | 199 perror("Process start: setting signal handler failed"); |
167 } | 200 } |
168 pid = fork(); | 201 pid = fork(); |
169 if (pid < 0) { | 202 if (pid < 0) { |
170 SetChildOsErrorMessage(os_error_message, os_error_message_len); | 203 SetChildOsErrorMessage(os_error_message, os_error_message_len); |
171 close(read_in[0]); | 204 close(read_in[0]); |
172 close(read_in[1]); | 205 close(read_in[1]); |
173 close(read_err[0]); | 206 close(read_err[0]); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
224 close(read_in[0]); | 257 close(read_in[0]); |
225 close(read_in[1]); | 258 close(read_in[1]); |
226 close(read_err[0]); | 259 close(read_err[0]); |
227 close(read_err[1]); | 260 close(read_err[1]); |
228 close(write_out[0]); | 261 close(write_out[0]); |
229 close(write_out[1]); | 262 close(write_out[1]); |
230 fprintf(stderr, "Error pipe creation failed: %s\n", os_error_message); | 263 fprintf(stderr, "Error pipe creation failed: %s\n", os_error_message); |
231 return errno; | 264 return errno; |
232 } | 265 } |
233 | 266 |
234 ActiveProcess* activeProcess = new ActiveProcess(); | 267 ProcessInfo* process = new ProcessInfo(pid, event_fds[1]); |
235 activeProcess->pid = pid; | 268 AddProcess(process); |
236 activeProcess->fd = event_fds[1]; | |
237 activeProcesses.Add(*activeProcess); | |
238 *exit_event = event_fds[0]; | 269 *exit_event = event_fds[0]; |
239 FDUtils::SetNonBlocking(event_fds[0]); | 270 FDUtils::SetNonBlocking(event_fds[0]); |
240 | 271 |
241 // Notify child process to start. | 272 // Notify child process to start. |
242 char msg = '1'; | 273 char msg = '1'; |
243 result = FDUtils::WriteToBlocking(read_in[1], &msg, sizeof(msg)); | 274 result = FDUtils::WriteToBlocking(read_in[1], &msg, sizeof(msg)); |
244 if (result != sizeof(msg)) { | 275 if (result != sizeof(msg)) { |
245 perror("Failed sending notification message"); | 276 perror("Failed sending notification message"); |
246 } | 277 } |
247 | 278 |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
293 } | 324 } |
294 | 325 |
295 | 326 |
296 bool Process::Kill(intptr_t id) { | 327 bool Process::Kill(intptr_t id) { |
297 int result = kill(id, SIGKILL); | 328 int result = kill(id, SIGKILL); |
298 if (result == -1) { | 329 if (result == -1) { |
299 return false; | 330 return false; |
300 } | 331 } |
301 return true; | 332 return true; |
302 } | 333 } |
| 334 |
| 335 |
| 336 void Process::Exit(intptr_t id) { |
| 337 RemoveProcess(id); |
| 338 } |
OLD | NEW |