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

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

Issue 165723007: Move signal_blocker to platform and use it by default in TEMP_FAILURE_RETRY. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 10 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
OLDNEW
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
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
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
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
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
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
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
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)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698