OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 "platform/globals.h" | 5 #include "platform/globals.h" |
6 #if defined(TARGET_OS_LINUX) | 6 #if defined(TARGET_OS_LINUX) |
7 | 7 |
8 #include "bin/process.h" | 8 #include "bin/process.h" |
9 | 9 |
10 #include <errno.h> // NOLINT | 10 #include <errno.h> // NOLINT |
11 #include <fcntl.h> // NOLINT | 11 #include <fcntl.h> // NOLINT |
12 #include <poll.h> // NOLINT | 12 #include <poll.h> // NOLINT |
13 #include <stdio.h> // NOLINT | 13 #include <stdio.h> // NOLINT |
14 #include <stdlib.h> // NOLINT | 14 #include <stdlib.h> // NOLINT |
15 #include <string.h> // NOLINT | 15 #include <string.h> // NOLINT |
16 #include <sys/wait.h> // NOLINT | 16 #include <sys/wait.h> // NOLINT |
17 #include <unistd.h> // NOLINT | 17 #include <unistd.h> // NOLINT |
18 | 18 |
| 19 #include "platform/signal_blocker.h" |
19 #include "bin/fdutils.h" | 20 #include "bin/fdutils.h" |
20 #include "bin/log.h" | 21 #include "bin/log.h" |
21 #include "bin/signal_blocker.h" | |
22 #include "bin/thread.h" | 22 #include "bin/thread.h" |
23 | 23 |
24 | 24 |
25 extern char **environ; | 25 extern char **environ; |
26 | 26 |
27 | 27 |
28 namespace dart { | 28 namespace dart { |
29 namespace bin { | 29 namespace bin { |
30 | 30 |
31 // ProcessInfo is used to map a process id to the file descriptor for | 31 // ProcessInfo is used to map a process id to the file descriptor for |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
144 | 144 |
145 if (!running_) { | 145 if (!running_) { |
146 return; | 146 return; |
147 } | 147 } |
148 | 148 |
149 // Set terminate_done_ to false, so we can use it as a guard for our | 149 // Set terminate_done_ to false, so we can use it as a guard for our |
150 // monitor. | 150 // monitor. |
151 running_ = false; | 151 running_ = false; |
152 | 152 |
153 // Fork to wake up waitpid. | 153 // Fork to wake up waitpid. |
154 if (TEMP_FAILURE_RETRY(fork()) == 0) { | 154 if (fork() == 0) { |
155 exit(0); | 155 exit(0); |
156 } | 156 } |
157 | 157 |
158 monitor_->Notify(); | 158 monitor_->Notify(); |
159 | 159 |
160 while (!terminate_done_) { | 160 while (!terminate_done_) { |
161 monitor_->Wait(dart::Monitor::kNoTimeout); | 161 monitor_->Wait(dart::Monitor::kNoTimeout); |
162 } | 162 } |
163 } | 163 } |
164 | 164 |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
267 intptr_t* id, | 267 intptr_t* id, |
268 intptr_t* exit_event, | 268 intptr_t* exit_event, |
269 char** os_error_message) { | 269 char** os_error_message) { |
270 pid_t pid; | 270 pid_t pid; |
271 int read_in[2]; // Pipe for stdout to child process. | 271 int read_in[2]; // Pipe for stdout to child process. |
272 int read_err[2]; // Pipe for stderr to child process. | 272 int read_err[2]; // Pipe for stderr to child process. |
273 int write_out[2]; // Pipe for stdin to child process. | 273 int write_out[2]; // Pipe for stdin to child process. |
274 int exec_control[2]; // Pipe to get the result from exec. | 274 int exec_control[2]; // Pipe to get the result from exec. |
275 int result; | 275 int result; |
276 | 276 |
277 result = TEMP_FAILURE_RETRY(pipe(read_in)); | 277 result = pipe(read_in); |
278 if (result < 0) { | 278 if (result < 0) { |
279 SetChildOsErrorMessage(os_error_message); | 279 SetChildOsErrorMessage(os_error_message); |
280 Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message); | 280 Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message); |
281 return errno; | 281 return errno; |
282 } | 282 } |
283 FDUtils::SetCloseOnExec(read_in[0]); | 283 FDUtils::SetCloseOnExec(read_in[0]); |
284 | 284 |
285 result = TEMP_FAILURE_RETRY(pipe(read_err)); | 285 result = pipe(read_err); |
286 if (result < 0) { | 286 if (result < 0) { |
287 SetChildOsErrorMessage(os_error_message); | 287 SetChildOsErrorMessage(os_error_message); |
288 TEMP_FAILURE_RETRY(close(read_in[0])); | 288 TEMP_FAILURE_RETRY(close(read_in[0])); |
289 TEMP_FAILURE_RETRY(close(read_in[1])); | 289 TEMP_FAILURE_RETRY(close(read_in[1])); |
290 Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message); | 290 Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message); |
291 return errno; | 291 return errno; |
292 } | 292 } |
293 FDUtils::SetCloseOnExec(read_err[0]); | 293 FDUtils::SetCloseOnExec(read_err[0]); |
294 | 294 |
295 result = TEMP_FAILURE_RETRY(pipe(write_out)); | 295 result = pipe(write_out); |
296 if (result < 0) { | 296 if (result < 0) { |
297 SetChildOsErrorMessage(os_error_message); | 297 SetChildOsErrorMessage(os_error_message); |
298 TEMP_FAILURE_RETRY(close(read_in[0])); | 298 TEMP_FAILURE_RETRY(close(read_in[0])); |
299 TEMP_FAILURE_RETRY(close(read_in[1])); | 299 TEMP_FAILURE_RETRY(close(read_in[1])); |
300 TEMP_FAILURE_RETRY(close(read_err[0])); | 300 TEMP_FAILURE_RETRY(close(read_err[0])); |
301 TEMP_FAILURE_RETRY(close(read_err[1])); | 301 TEMP_FAILURE_RETRY(close(read_err[1])); |
302 Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message); | 302 Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message); |
303 return errno; | 303 return errno; |
304 } | 304 } |
305 FDUtils::SetCloseOnExec(write_out[1]); | 305 FDUtils::SetCloseOnExec(write_out[1]); |
306 | 306 |
307 result = TEMP_FAILURE_RETRY(pipe(exec_control)); | 307 result = pipe(exec_control); |
308 if (result < 0) { | 308 if (result < 0) { |
309 SetChildOsErrorMessage(os_error_message); | 309 SetChildOsErrorMessage(os_error_message); |
310 TEMP_FAILURE_RETRY(close(read_in[0])); | 310 TEMP_FAILURE_RETRY(close(read_in[0])); |
311 TEMP_FAILURE_RETRY(close(read_in[1])); | 311 TEMP_FAILURE_RETRY(close(read_in[1])); |
312 TEMP_FAILURE_RETRY(close(read_err[0])); | 312 TEMP_FAILURE_RETRY(close(read_err[0])); |
313 TEMP_FAILURE_RETRY(close(read_err[1])); | 313 TEMP_FAILURE_RETRY(close(read_err[1])); |
314 TEMP_FAILURE_RETRY(close(write_out[0])); | 314 TEMP_FAILURE_RETRY(close(write_out[0])); |
315 TEMP_FAILURE_RETRY(close(write_out[1])); | 315 TEMP_FAILURE_RETRY(close(write_out[1])); |
316 Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message); | 316 Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message); |
317 return errno; | 317 return errno; |
(...skipping 24 matching lines...) Expand all Loading... |
342 | 342 |
343 char** program_environment = NULL; | 343 char** program_environment = NULL; |
344 if (environment != NULL) { | 344 if (environment != NULL) { |
345 program_environment = new char*[environment_length + 1]; | 345 program_environment = new char*[environment_length + 1]; |
346 for (int i = 0; i < environment_length; i++) { | 346 for (int i = 0; i < environment_length; i++) { |
347 program_environment[i] = environment[i]; | 347 program_environment[i] = environment[i]; |
348 } | 348 } |
349 program_environment[environment_length] = NULL; | 349 program_environment[environment_length] = NULL; |
350 } | 350 } |
351 | 351 |
352 pid = TEMP_FAILURE_RETRY(fork()); | 352 pid = fork(); |
353 if (pid < 0) { | 353 if (pid < 0) { |
354 SetChildOsErrorMessage(os_error_message); | 354 SetChildOsErrorMessage(os_error_message); |
355 delete[] program_arguments; | 355 delete[] program_arguments; |
356 TEMP_FAILURE_RETRY(close(read_in[0])); | 356 TEMP_FAILURE_RETRY(close(read_in[0])); |
357 TEMP_FAILURE_RETRY(close(read_in[1])); | 357 TEMP_FAILURE_RETRY(close(read_in[1])); |
358 TEMP_FAILURE_RETRY(close(read_err[0])); | 358 TEMP_FAILURE_RETRY(close(read_err[0])); |
359 TEMP_FAILURE_RETRY(close(read_err[1])); | 359 TEMP_FAILURE_RETRY(close(read_err[1])); |
360 TEMP_FAILURE_RETRY(close(write_out[0])); | 360 TEMP_FAILURE_RETRY(close(write_out[0])); |
361 TEMP_FAILURE_RETRY(close(write_out[1])); | 361 TEMP_FAILURE_RETRY(close(write_out[1])); |
362 TEMP_FAILURE_RETRY(close(exec_control[0])); | 362 TEMP_FAILURE_RETRY(close(exec_control[0])); |
(...skipping 21 matching lines...) Expand all Loading... |
384 if (TEMP_FAILURE_RETRY(dup2(read_in[1], STDOUT_FILENO)) == -1) { | 384 if (TEMP_FAILURE_RETRY(dup2(read_in[1], STDOUT_FILENO)) == -1) { |
385 ReportChildError(exec_control[1]); | 385 ReportChildError(exec_control[1]); |
386 } | 386 } |
387 TEMP_FAILURE_RETRY(close(read_in[1])); | 387 TEMP_FAILURE_RETRY(close(read_in[1])); |
388 | 388 |
389 if (TEMP_FAILURE_RETRY(dup2(read_err[1], STDERR_FILENO)) == -1) { | 389 if (TEMP_FAILURE_RETRY(dup2(read_err[1], STDERR_FILENO)) == -1) { |
390 ReportChildError(exec_control[1]); | 390 ReportChildError(exec_control[1]); |
391 } | 391 } |
392 TEMP_FAILURE_RETRY(close(read_err[1])); | 392 TEMP_FAILURE_RETRY(close(read_err[1])); |
393 | 393 |
394 if (working_directory != NULL && | 394 if (working_directory != NULL && chdir(working_directory) == -1) { |
395 TEMP_FAILURE_RETRY(chdir(working_directory)) == -1) { | |
396 ReportChildError(exec_control[1]); | 395 ReportChildError(exec_control[1]); |
397 } | 396 } |
398 | 397 |
399 if (program_environment != NULL) { | 398 if (program_environment != NULL) { |
400 environ = program_environment; | 399 environ = program_environment; |
401 } | 400 } |
402 | 401 |
403 TEMP_FAILURE_RETRY( | 402 execvp(path, const_cast<char* const*>(program_arguments)); |
404 execvp(path, const_cast<char* const*>(program_arguments))); | |
405 | 403 |
406 ReportChildError(exec_control[1]); | 404 ReportChildError(exec_control[1]); |
407 } | 405 } |
408 | 406 |
409 // Be sure to listen for exit-codes, now we have a child-process. | 407 // Be sure to listen for exit-codes, now we have a child-process. |
410 ExitCodeHandler::ProcessStarted(); | 408 ExitCodeHandler::ProcessStarted(); |
411 | 409 |
412 // The arguments and environment for the spawned process are not needed | 410 // The arguments and environment for the spawned process are not needed |
413 // any longer. | 411 // any longer. |
414 delete[] program_arguments; | 412 delete[] program_arguments; |
415 delete[] program_environment; | 413 delete[] program_environment; |
416 | 414 |
417 int event_fds[2]; | 415 int event_fds[2]; |
418 result = TEMP_FAILURE_RETRY(pipe(event_fds)); | 416 result = pipe(event_fds); |
419 if (result < 0) { | 417 if (result < 0) { |
420 SetChildOsErrorMessage(os_error_message); | 418 SetChildOsErrorMessage(os_error_message); |
421 TEMP_FAILURE_RETRY(close(read_in[0])); | 419 TEMP_FAILURE_RETRY(close(read_in[0])); |
422 TEMP_FAILURE_RETRY(close(read_in[1])); | 420 TEMP_FAILURE_RETRY(close(read_in[1])); |
423 TEMP_FAILURE_RETRY(close(read_err[0])); | 421 TEMP_FAILURE_RETRY(close(read_err[0])); |
424 TEMP_FAILURE_RETRY(close(read_err[1])); | 422 TEMP_FAILURE_RETRY(close(read_err[1])); |
425 TEMP_FAILURE_RETRY(close(write_out[0])); | 423 TEMP_FAILURE_RETRY(close(write_out[0])); |
426 TEMP_FAILURE_RETRY(close(write_out[1])); | 424 TEMP_FAILURE_RETRY(close(write_out[1])); |
427 Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message); | 425 Log::PrintErr("Error pipe creation failed: %s\n", *os_error_message); |
428 return errno; | 426 return errno; |
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
611 intptr_t exit_code = exit_code_data.ints[0]; | 609 intptr_t exit_code = exit_code_data.ints[0]; |
612 intptr_t negative = exit_code_data.ints[1]; | 610 intptr_t negative = exit_code_data.ints[1]; |
613 if (negative) exit_code = -exit_code; | 611 if (negative) exit_code = -exit_code; |
614 result->set_exit_code(exit_code); | 612 result->set_exit_code(exit_code); |
615 | 613 |
616 return true; | 614 return true; |
617 } | 615 } |
618 | 616 |
619 | 617 |
620 bool Process::Kill(intptr_t id, int signal) { | 618 bool Process::Kill(intptr_t id, int signal) { |
621 return (TEMP_FAILURE_RETRY(kill(id, signal)) != -1); | 619 return kill(id, signal) != -1; |
622 } | 620 } |
623 | 621 |
624 | 622 |
625 void Process::TerminateExitCodeHandler() { | 623 void Process::TerminateExitCodeHandler() { |
626 ExitCodeHandler::TerminateExitCodeThread(); | 624 ExitCodeHandler::TerminateExitCodeThread(); |
627 } | 625 } |
628 | 626 |
629 | 627 |
630 intptr_t Process::CurrentProcessId() { | 628 intptr_t Process::CurrentProcessId() { |
631 return static_cast<intptr_t>(getpid()); | 629 return static_cast<intptr_t>(getpid()); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
666 intptr_t Process::SetSignalHandler(intptr_t signal) { | 664 intptr_t Process::SetSignalHandler(intptr_t signal) { |
667 bool found = false; | 665 bool found = false; |
668 for (int i = 0; i < kSignalsCount; i++) { | 666 for (int i = 0; i < kSignalsCount; i++) { |
669 if (kSignals[i] == signal) { | 667 if (kSignals[i] == signal) { |
670 found = true; | 668 found = true; |
671 break; | 669 break; |
672 } | 670 } |
673 } | 671 } |
674 if (!found) return -1; | 672 if (!found) return -1; |
675 int fds[2]; | 673 int fds[2]; |
676 if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(pipe(fds)) != 0) { | 674 if (pipe(fds) != 0) { |
677 return -1; | 675 return -1; |
678 } | 676 } |
679 if (!FDUtils::SetNonBlocking(fds[0])) { | 677 if (!FDUtils::SetNonBlocking(fds[0])) { |
680 VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(fds[0])); | 678 VOID_TEMP_FAILURE_RETRY(close(fds[0])); |
681 VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(fds[1])); | 679 VOID_TEMP_FAILURE_RETRY(close(fds[1])); |
682 return -1; | 680 return -1; |
683 } | 681 } |
684 ThreadSignalBlocker blocker(kSignalsCount, kSignals); | 682 ThreadSignalBlocker blocker(kSignalsCount, kSignals); |
685 MutexLocker lock(signal_mutex); | 683 MutexLocker lock(signal_mutex); |
686 SignalInfo* handler = signal_handlers; | 684 SignalInfo* handler = signal_handlers; |
687 bool listen = true; | 685 bool listen = true; |
688 while (handler != NULL) { | 686 while (handler != NULL) { |
689 if (handler->signal() == signal) { | 687 if (handler->signal() == signal) { |
690 listen = false; | 688 listen = false; |
691 break; | 689 break; |
692 } | 690 } |
693 handler = handler->next(); | 691 handler = handler->next(); |
694 } | 692 } |
695 if (listen) { | 693 if (listen) { |
696 struct sigaction act; | 694 struct sigaction act; |
697 bzero(&act, sizeof(act)); | 695 bzero(&act, sizeof(act)); |
698 act.sa_handler = SignalHandler; | 696 act.sa_handler = SignalHandler; |
699 sigemptyset(&act.sa_mask); | 697 sigemptyset(&act.sa_mask); |
700 for (int i = 0; i < kSignalsCount; i++) { | 698 for (int i = 0; i < kSignalsCount; i++) { |
701 sigaddset(&act.sa_mask, kSignals[i]); | 699 sigaddset(&act.sa_mask, kSignals[i]); |
702 } | 700 } |
703 int status = TEMP_FAILURE_RETRY_BLOCK_SIGNALS( | 701 int status = sigaction(signal, &act, NULL); |
704 sigaction(signal, &act, NULL)); | |
705 if (status < 0) { | 702 if (status < 0) { |
706 VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(fds[0])); | 703 VOID_TEMP_FAILURE_RETRY(close(fds[0])); |
707 VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(fds[1])); | 704 VOID_TEMP_FAILURE_RETRY(close(fds[1])); |
708 return -1; | 705 return -1; |
709 } | 706 } |
710 } | 707 } |
711 if (signal_handlers == NULL) { | 708 if (signal_handlers == NULL) { |
712 signal_handlers = new SignalInfo(fds[1], signal); | 709 signal_handlers = new SignalInfo(fds[1], signal); |
713 } else { | 710 } else { |
714 new SignalInfo(fds[1], signal, signal_handlers); | 711 new SignalInfo(fds[1], signal, signal_handlers); |
715 } | 712 } |
716 return fds[0]; | 713 return fds[0]; |
717 } | 714 } |
(...skipping 16 matching lines...) Expand all Loading... |
734 } | 731 } |
735 } | 732 } |
736 SignalInfo* next = handler->next(); | 733 SignalInfo* next = handler->next(); |
737 if (remove) delete handler; | 734 if (remove) delete handler; |
738 handler = next; | 735 handler = next; |
739 } | 736 } |
740 if (unlisten) { | 737 if (unlisten) { |
741 struct sigaction act; | 738 struct sigaction act; |
742 bzero(&act, sizeof(act)); | 739 bzero(&act, sizeof(act)); |
743 act.sa_handler = SIG_DFL; | 740 act.sa_handler = SIG_DFL; |
744 VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(sigaction(signal, &act, NULL)); | 741 sigaction(signal, &act, NULL); |
745 } | 742 } |
746 } | 743 } |
747 | 744 |
748 } // namespace bin | 745 } // namespace bin |
749 } // namespace dart | 746 } // namespace dart |
750 | 747 |
751 #endif // defined(TARGET_OS_LINUX) | 748 #endif // defined(TARGET_OS_LINUX) |
OLD | NEW |