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

Side by Side Diff: runtime/bin/process_linux.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_impl.dart ('k') | runtime/bin/process_macos.cc » ('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"
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
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
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
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 }
OLDNEW
« no previous file with comments | « runtime/bin/process_impl.dart ('k') | runtime/bin/process_macos.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698