Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(107)

Side by Side Diff: runtime/bin/process_macos.cc

Issue 8227010: Fix deadlock in process exit handling (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Addressed review comments from @ager Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/bin/process_linux.cc ('k') | runtime/tests/dart/dart.status » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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 }
OLDNEW
« no previous file with comments | « runtime/bin/process_linux.cc ('k') | runtime/tests/dart/dart.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698