| 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 | 
|---|