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