| 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_ANDROID) | 6 #if defined(TARGET_OS_ANDROID) |
| 7 | 7 |
| 8 #include "bin/process.h" | 8 #include "bin/process.h" |
| 9 | 9 |
| 10 #include <errno.h> // NOLINT | 10 #include <errno.h> // NOLINT |
| (...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 231 | 231 |
| 232 | 232 |
| 233 class ProcessStarter { | 233 class ProcessStarter { |
| 234 public: | 234 public: |
| 235 ProcessStarter(const char* path, | 235 ProcessStarter(const char* path, |
| 236 char* arguments[], | 236 char* arguments[], |
| 237 intptr_t arguments_length, | 237 intptr_t arguments_length, |
| 238 const char* working_directory, | 238 const char* working_directory, |
| 239 char* environment[], | 239 char* environment[], |
| 240 intptr_t environment_length, | 240 intptr_t environment_length, |
| 241 bool detach, | 241 ProcessStartMode mode, |
| 242 intptr_t* in, | 242 intptr_t* in, |
| 243 intptr_t* out, | 243 intptr_t* out, |
| 244 intptr_t* err, | 244 intptr_t* err, |
| 245 intptr_t* id, | 245 intptr_t* id, |
| 246 intptr_t* exit_event, | 246 intptr_t* exit_event, |
| 247 char** os_error_message) | 247 char** os_error_message) |
| 248 : path_(path), | 248 : path_(path), |
| 249 working_directory_(working_directory), | 249 working_directory_(working_directory), |
| 250 detach_(detach), | 250 mode_(mode), |
| 251 in_(in), | 251 in_(in), |
| 252 out_(out), | 252 out_(out), |
| 253 err_(err), | 253 err_(err), |
| 254 id_(id), | 254 id_(id), |
| 255 exit_event_(exit_event), | 255 exit_event_(exit_event), |
| 256 os_error_message_(os_error_message) { | 256 os_error_message_(os_error_message) { |
| 257 read_in_[0] = -1; | 257 read_in_[0] = -1; |
| 258 read_in_[1] = -1; | 258 read_in_[1] = -1; |
| 259 read_err_[0] = -1; | 259 read_err_[0] = -1; |
| 260 read_err_[1] = -1; | 260 read_err_[1] = -1; |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 301 // This runs in the new process. | 301 // This runs in the new process. |
| 302 NewProcess(); | 302 NewProcess(); |
| 303 } | 303 } |
| 304 | 304 |
| 305 // This runs in the original process. | 305 // This runs in the original process. |
| 306 | 306 |
| 307 // Be sure to listen for exit-codes, now we have a child-process. | 307 // Be sure to listen for exit-codes, now we have a child-process. |
| 308 ExitCodeHandler::ProcessStarted(); | 308 ExitCodeHandler::ProcessStarted(); |
| 309 | 309 |
| 310 // Register the child process if not detached. | 310 // Register the child process if not detached. |
| 311 if (!detach_) { | 311 if (mode_ == kNormal) { |
| 312 err = RegisterProcess(pid); | 312 err = RegisterProcess(pid); |
| 313 if (err != 0) return err; | 313 if (err != 0) return err; |
| 314 } | 314 } |
| 315 | 315 |
| 316 // Notify child process to start. This is done to delay the call to exec | 316 // Notify child process to start. This is done to delay the call to exec |
| 317 // until the process is registered above, and we are ready to receive the | 317 // until the process is registered above, and we are ready to receive the |
| 318 // exit code. | 318 // exit code. |
| 319 char msg = '1'; | 319 char msg = '1'; |
| 320 int bytes_written = | 320 int bytes_written = |
| 321 FDUtils::WriteToBlocking(read_in_[1], &msg, sizeof(msg)); | 321 FDUtils::WriteToBlocking(read_in_[1], &msg, sizeof(msg)); |
| 322 if (bytes_written != sizeof(msg)) { | 322 if (bytes_written != sizeof(msg)) { |
| 323 return CleanupAndReturnError(); | 323 return CleanupAndReturnError(); |
| 324 } | 324 } |
| 325 | 325 |
| 326 // Read the result of executing the child process. | 326 // Read the result of executing the child process. |
| 327 VOID_TEMP_FAILURE_RETRY(close(exec_control_[1])); | 327 VOID_TEMP_FAILURE_RETRY(close(exec_control_[1])); |
| 328 exec_control_[1] = -1; | 328 exec_control_[1] = -1; |
| 329 if (!detach_) { | 329 if (mode_ == kNormal) { |
| 330 err = ReadExecResult(); | 330 err = ReadExecResult(); |
| 331 } else { | 331 } else { |
| 332 err = ReadDetachedExecResult(&pid); | 332 err = ReadDetachedExecResult(&pid); |
| 333 } | 333 } |
| 334 VOID_TEMP_FAILURE_RETRY(close(exec_control_[0])); | 334 VOID_TEMP_FAILURE_RETRY(close(exec_control_[0])); |
| 335 exec_control_[0] = -1; | 335 exec_control_[0] = -1; |
| 336 | 336 |
| 337 // Return error code if any failures. | 337 // Return error code if any failures. |
| 338 if (err != 0) { | 338 if (err != 0) { |
| 339 if (!detach_) { | 339 if (mode_ == kNormal) { |
| 340 // Since exec() failed, we're not interested in the exit code. | 340 // Since exec() failed, we're not interested in the exit code. |
| 341 // We close the reading side of the exit code pipe here. | 341 // We close the reading side of the exit code pipe here. |
| 342 // GetProcessExitCodes will get a broken pipe error when it | 342 // GetProcessExitCodes will get a broken pipe error when it |
| 343 // tries to write to the writing side of the pipe and it will | 343 // tries to write to the writing side of the pipe and it will |
| 344 // ignore the error. | 344 // ignore the error. |
| 345 VOID_TEMP_FAILURE_RETRY(close(*exit_event_)); | 345 VOID_TEMP_FAILURE_RETRY(close(*exit_event_)); |
| 346 *exit_event_ = -1; | 346 *exit_event_ = -1; |
| 347 } | 347 } |
| 348 CloseAllPipes(); | 348 CloseAllPipes(); |
| 349 return err; | 349 return err; |
| 350 } | 350 } |
| 351 | 351 |
| 352 if (!detach_) { | 352 if (mode_ != kDetached) { |
| 353 // Connect stdio, stdout and stderr. | 353 // Connect stdio, stdout and stderr. |
| 354 FDUtils::SetNonBlocking(read_in_[0]); | 354 FDUtils::SetNonBlocking(read_in_[0]); |
| 355 *in_ = read_in_[0]; | 355 *in_ = read_in_[0]; |
| 356 VOID_TEMP_FAILURE_RETRY(close(read_in_[1])); | 356 VOID_TEMP_FAILURE_RETRY(close(read_in_[1])); |
| 357 FDUtils::SetNonBlocking(write_out_[1]); | 357 FDUtils::SetNonBlocking(write_out_[1]); |
| 358 *out_ = write_out_[1]; | 358 *out_ = write_out_[1]; |
| 359 VOID_TEMP_FAILURE_RETRY(close(write_out_[0])); | 359 VOID_TEMP_FAILURE_RETRY(close(write_out_[0])); |
| 360 FDUtils::SetNonBlocking(read_err_[0]); | 360 FDUtils::SetNonBlocking(read_err_[0]); |
| 361 *err_ = read_err_[0]; | 361 *err_ = read_err_[0]; |
| 362 VOID_TEMP_FAILURE_RETRY(close(read_err_[1])); | 362 VOID_TEMP_FAILURE_RETRY(close(read_err_[1])); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 388 | 388 |
| 389 // For a detached process the pipe to connect stdout is still used for | 389 // For a detached process the pipe to connect stdout is still used for |
| 390 // signaling when to do the first fork. | 390 // signaling when to do the first fork. |
| 391 result = TEMP_FAILURE_RETRY(pipe(read_in_)); | 391 result = TEMP_FAILURE_RETRY(pipe(read_in_)); |
| 392 if (result < 0) { | 392 if (result < 0) { |
| 393 return CleanupAndReturnError(); | 393 return CleanupAndReturnError(); |
| 394 } | 394 } |
| 395 FDUtils::SetCloseOnExec(read_in_[0]); | 395 FDUtils::SetCloseOnExec(read_in_[0]); |
| 396 | 396 |
| 397 // For detached processes the pipe to connect stderr and stdin are not used. | 397 // For detached processes the pipe to connect stderr and stdin are not used. |
| 398 if (!detach_) { | 398 if (mode_ != kDetached) { |
| 399 result = TEMP_FAILURE_RETRY(pipe(read_err_)); | 399 result = TEMP_FAILURE_RETRY(pipe(read_err_)); |
| 400 if (result < 0) { | 400 if (result < 0) { |
| 401 return CleanupAndReturnError(); | 401 return CleanupAndReturnError(); |
| 402 } | 402 } |
| 403 FDUtils::SetCloseOnExec(read_err_[0]); | 403 FDUtils::SetCloseOnExec(read_err_[0]); |
| 404 | 404 |
| 405 result = TEMP_FAILURE_RETRY(pipe(write_out_)); | 405 result = TEMP_FAILURE_RETRY(pipe(write_out_)); |
| 406 if (result < 0) { | 406 if (result < 0) { |
| 407 return CleanupAndReturnError(); | 407 return CleanupAndReturnError(); |
| 408 } | 408 } |
| 409 FDUtils::SetCloseOnExec(write_out_[1]); | 409 FDUtils::SetCloseOnExec(write_out_[1]); |
| 410 } | 410 } |
| 411 | 411 |
| 412 return 0; | 412 return 0; |
| 413 } | 413 } |
| 414 | 414 |
| 415 | 415 |
| 416 void NewProcess() { | 416 void NewProcess() { |
| 417 // Wait for parent process before setting up the child process. | 417 // Wait for parent process before setting up the child process. |
| 418 char msg; | 418 char msg; |
| 419 int bytes_read = FDUtils::ReadFromBlocking(read_in_[0], &msg, sizeof(msg)); | 419 int bytes_read = FDUtils::ReadFromBlocking(read_in_[0], &msg, sizeof(msg)); |
| 420 if (bytes_read != sizeof(msg)) { | 420 if (bytes_read != sizeof(msg)) { |
| 421 perror("Failed receiving notification message"); | 421 perror("Failed receiving notification message"); |
| 422 exit(1); | 422 exit(1); |
| 423 } | 423 } |
| 424 if (detach_) { | 424 if (mode_ == kNormal) { |
| 425 ExecProcess(); |
| 426 } else { |
| 425 ExecDetachedProcess(); | 427 ExecDetachedProcess(); |
| 426 } else { | |
| 427 ExecProcess(); | |
| 428 } | 428 } |
| 429 } | 429 } |
| 430 | 430 |
| 431 | 431 |
| 432 void ExecProcess() { | 432 void ExecProcess() { |
| 433 VOID_TEMP_FAILURE_RETRY(close(write_out_[1])); | 433 VOID_TEMP_FAILURE_RETRY(close(write_out_[1])); |
| 434 VOID_TEMP_FAILURE_RETRY(close(read_in_[0])); | 434 VOID_TEMP_FAILURE_RETRY(close(read_in_[0])); |
| 435 VOID_TEMP_FAILURE_RETRY(close(read_err_[0])); | 435 VOID_TEMP_FAILURE_RETRY(close(read_err_[0])); |
| 436 VOID_TEMP_FAILURE_RETRY(close(exec_control_[0])); | 436 VOID_TEMP_FAILURE_RETRY(close(exec_control_[0])); |
| 437 | 437 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 460 } | 460 } |
| 461 | 461 |
| 462 VOID_TEMP_FAILURE_RETRY( | 462 VOID_TEMP_FAILURE_RETRY( |
| 463 execvp(path_, const_cast<char* const*>(program_arguments_))); | 463 execvp(path_, const_cast<char* const*>(program_arguments_))); |
| 464 | 464 |
| 465 ReportChildError(); | 465 ReportChildError(); |
| 466 } | 466 } |
| 467 | 467 |
| 468 | 468 |
| 469 void ExecDetachedProcess() { | 469 void ExecDetachedProcess() { |
| 470 ASSERT(write_out_[0] == -1); | 470 if (mode_ == kDetached) { |
| 471 ASSERT(write_out_[1] == -1); | 471 ASSERT(write_out_[0] == -1); |
| 472 ASSERT(read_err_[0] == -1); | 472 ASSERT(write_out_[1] == -1); |
| 473 ASSERT(read_err_[1] == -1); | 473 ASSERT(read_err_[0] == -1); |
| 474 // For a detached process the pipe to connect stdout is only used for | 474 ASSERT(read_err_[1] == -1); |
| 475 // signaling when to do the first fork. | 475 // For a detached process the pipe to connect stdout is only used for |
| 476 VOID_TEMP_FAILURE_RETRY(close(read_in_[0])); | 476 // signaling when to do the first fork. |
| 477 VOID_TEMP_FAILURE_RETRY(close(read_in_[1])); | 477 VOID_TEMP_FAILURE_RETRY(close(read_in_[0])); |
| 478 read_in_[0] = -1; |
| 479 VOID_TEMP_FAILURE_RETRY(close(read_in_[1])); |
| 480 read_in_[1] = -1; |
| 481 } else { |
| 482 // Don't close any fds if keeping stdio open to the detached process. |
| 483 ASSERT(mode_ == kDetachedWithStdio); |
| 484 } |
| 478 // Fork once more to start a new session. | 485 // Fork once more to start a new session. |
| 479 pid_t pid = TEMP_FAILURE_RETRY(fork()); | 486 pid_t pid = TEMP_FAILURE_RETRY(fork()); |
| 480 if (pid < 0) { | 487 if (pid < 0) { |
| 481 ReportChildError(); | 488 ReportChildError(); |
| 482 } else if (pid == 0) { | 489 } else if (pid == 0) { |
| 483 // Start a new session. | 490 // Start a new session. |
| 484 if (TEMP_FAILURE_RETRY(setsid()) == -1) { | 491 if (TEMP_FAILURE_RETRY(setsid()) == -1) { |
| 485 ReportChildError(); | 492 ReportChildError(); |
| 486 } else { | 493 } else { |
| 487 // Do a final fork to not be the session leader. | 494 // Do a final fork to not be the session leader. |
| 488 pid = TEMP_FAILURE_RETRY(fork()); | 495 pid = TEMP_FAILURE_RETRY(fork()); |
| 489 if (pid < 0) { | 496 if (pid < 0) { |
| 490 ReportChildError(); | 497 ReportChildError(); |
| 491 } else if (pid == 0) { | 498 } else if (pid == 0) { |
| 492 // Close all open file descriptors except for exec_control_[1]. | 499 if (mode_ == kDetached) { |
| 493 int max_fds = sysconf(_SC_OPEN_MAX); | 500 SetupDetached(); |
| 494 if (max_fds == -1) max_fds = _POSIX_OPEN_MAX; | 501 } else { |
| 495 for (int fd = 0; fd < max_fds; fd++) { | 502 SetupDetachedWithStdio(); |
| 496 if (fd != exec_control_[1]) { | |
| 497 VOID_TEMP_FAILURE_RETRY(close(fd)); | |
| 498 } | |
| 499 } | 503 } |
| 500 | 504 |
| 501 // Re-open stdin, stdout and stderr and connect them to /dev/null. | 505 if (working_directory_ != NULL && |
| 502 // The loop above should already have closed all of them, so | 506 TEMP_FAILURE_RETRY(chdir(working_directory_)) == -1) { |
| 503 // creating new file descriptors should start at STDIN_FILENO. | |
| 504 int fd = TEMP_FAILURE_RETRY(open("/dev/null", O_RDWR)); | |
| 505 if (fd != STDIN_FILENO) { | |
| 506 ReportChildError(); | |
| 507 } | |
| 508 if (TEMP_FAILURE_RETRY(dup2(STDIN_FILENO, STDOUT_FILENO)) != | |
| 509 STDOUT_FILENO) { | |
| 510 ReportChildError(); | |
| 511 } | |
| 512 if (TEMP_FAILURE_RETRY(dup2(STDIN_FILENO, STDERR_FILENO)) != | |
| 513 STDERR_FILENO) { | |
| 514 ReportChildError(); | 507 ReportChildError(); |
| 515 } | 508 } |
| 516 | 509 |
| 517 // Report the final PID and do the exec. | 510 // Report the final PID and do the exec. |
| 518 ReportPid(getpid()); // getpid cannot fail. | 511 ReportPid(getpid()); // getpid cannot fail. |
| 519 VOID_TEMP_FAILURE_RETRY( | 512 VOID_TEMP_FAILURE_RETRY( |
| 520 execvp(path_, const_cast<char* const*>(program_arguments_))); | 513 execvp(path_, const_cast<char* const*>(program_arguments_))); |
| 521 ReportChildError(); | 514 ReportChildError(); |
| 522 } else { | 515 } else { |
| 523 // Exit the intermeiate process. | 516 // Exit the intermeiate process. |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 584 child_errno = result[1]; | 577 child_errno = result[1]; |
| 585 ReadChildError(); | 578 ReadChildError(); |
| 586 return child_errno; | 579 return child_errno; |
| 587 } else if (bytes_read == -1) { | 580 } else if (bytes_read == -1) { |
| 588 return errno; | 581 return errno; |
| 589 } | 582 } |
| 590 return 0; | 583 return 0; |
| 591 } | 584 } |
| 592 | 585 |
| 593 | 586 |
| 587 void SetupDetached() { |
| 588 ASSERT(mode_ == kDetached); |
| 589 |
| 590 // Close all open file descriptors except for exec_control_[1]. |
| 591 int max_fds = sysconf(_SC_OPEN_MAX); |
| 592 if (max_fds == -1) max_fds = _POSIX_OPEN_MAX; |
| 593 for (int fd = 0; fd < max_fds; fd++) { |
| 594 if (fd != exec_control_[1]) { |
| 595 VOID_TEMP_FAILURE_RETRY(close(fd)); |
| 596 } |
| 597 } |
| 598 |
| 599 // Re-open stdin, stdout and stderr and connect them to /dev/null. |
| 600 // The loop above should already have closed all of them, so |
| 601 // creating new file descriptors should start at STDIN_FILENO. |
| 602 int fd = TEMP_FAILURE_RETRY(open("/dev/null", O_RDWR)); |
| 603 if (fd != STDIN_FILENO) { |
| 604 ReportChildError(); |
| 605 } |
| 606 if (TEMP_FAILURE_RETRY(dup2(STDIN_FILENO, STDOUT_FILENO)) != |
| 607 STDOUT_FILENO) { |
| 608 ReportChildError(); |
| 609 } |
| 610 if (TEMP_FAILURE_RETRY(dup2(STDIN_FILENO, STDERR_FILENO)) != |
| 611 STDERR_FILENO) { |
| 612 ReportChildError(); |
| 613 } |
| 614 } |
| 615 |
| 616 void SetupDetachedWithStdio() { |
| 617 // Close all open file descriptors except for |
| 618 // exec_control_[1], write_out_[0], read_in_[1] and |
| 619 // read_err_[1]. |
| 620 int max_fds = sysconf(_SC_OPEN_MAX); |
| 621 if (max_fds == -1) max_fds = _POSIX_OPEN_MAX; |
| 622 for (int fd = 0; fd < max_fds; fd++) { |
| 623 if (fd != exec_control_[1] && |
| 624 fd != write_out_[0] && |
| 625 fd != read_in_[1] && |
| 626 fd != read_err_[1]) { |
| 627 VOID_TEMP_FAILURE_RETRY(close(fd)); |
| 628 } |
| 629 } |
| 630 |
| 631 if (TEMP_FAILURE_RETRY(dup2(write_out_[0], STDIN_FILENO)) == -1) { |
| 632 ReportChildError(); |
| 633 } |
| 634 VOID_TEMP_FAILURE_RETRY(close(write_out_[0])); |
| 635 |
| 636 if (TEMP_FAILURE_RETRY(dup2(read_in_[1], STDOUT_FILENO)) == -1) { |
| 637 ReportChildError(); |
| 638 } |
| 639 VOID_TEMP_FAILURE_RETRY(close(read_in_[1])); |
| 640 |
| 641 if (TEMP_FAILURE_RETRY(dup2(read_err_[1], STDERR_FILENO)) == -1) { |
| 642 ReportChildError(); |
| 643 } |
| 644 VOID_TEMP_FAILURE_RETRY(close(read_err_[1])); |
| 645 } |
| 646 |
| 647 |
| 594 int CleanupAndReturnError() { | 648 int CleanupAndReturnError() { |
| 595 int actual_errno = errno; | 649 int actual_errno = errno; |
| 596 // If CleanupAndReturnError is called without an actual errno make | 650 // If CleanupAndReturnError is called without an actual errno make |
| 597 // sure to return an error anyway. | 651 // sure to return an error anyway. |
| 598 if (actual_errno == 0) actual_errno = EPERM; | 652 if (actual_errno == 0) actual_errno = EPERM; |
| 599 SetChildOsErrorMessage(); | 653 SetChildOsErrorMessage(); |
| 600 CloseAllPipes(); | 654 CloseAllPipes(); |
| 601 return actual_errno; | 655 return actual_errno; |
| 602 } | 656 } |
| 603 | 657 |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 674 int read_in_[2]; // Pipe for stdout to child process. | 728 int read_in_[2]; // Pipe for stdout to child process. |
| 675 int read_err_[2]; // Pipe for stderr to child process. | 729 int read_err_[2]; // Pipe for stderr to child process. |
| 676 int write_out_[2]; // Pipe for stdin to child process. | 730 int write_out_[2]; // Pipe for stdin to child process. |
| 677 int exec_control_[2]; // Pipe to get the result from exec. | 731 int exec_control_[2]; // Pipe to get the result from exec. |
| 678 | 732 |
| 679 char** program_arguments_; | 733 char** program_arguments_; |
| 680 char** program_environment_; | 734 char** program_environment_; |
| 681 | 735 |
| 682 const char* path_; | 736 const char* path_; |
| 683 const char* working_directory_; | 737 const char* working_directory_; |
| 684 bool detach_; | 738 ProcessStartMode mode_; |
| 685 intptr_t* in_; | 739 intptr_t* in_; |
| 686 intptr_t* out_; | 740 intptr_t* out_; |
| 687 intptr_t* err_; | 741 intptr_t* err_; |
| 688 intptr_t* id_; | 742 intptr_t* id_; |
| 689 intptr_t* exit_event_; | 743 intptr_t* exit_event_; |
| 690 char** os_error_message_; | 744 char** os_error_message_; |
| 691 }; | 745 }; |
| 692 | 746 |
| 693 | 747 |
| 694 int Process::Start(const char* path, | 748 int Process::Start(const char* path, |
| 695 char* arguments[], | 749 char* arguments[], |
| 696 intptr_t arguments_length, | 750 intptr_t arguments_length, |
| 697 const char* working_directory, | 751 const char* working_directory, |
| 698 char* environment[], | 752 char* environment[], |
| 699 intptr_t environment_length, | 753 intptr_t environment_length, |
| 700 bool detach, | 754 ProcessStartMode mode, |
| 701 intptr_t* in, | 755 intptr_t* in, |
| 702 intptr_t* out, | 756 intptr_t* out, |
| 703 intptr_t* err, | 757 intptr_t* err, |
| 704 intptr_t* id, | 758 intptr_t* id, |
| 705 intptr_t* exit_event, | 759 intptr_t* exit_event, |
| 706 char** os_error_message) { | 760 char** os_error_message) { |
| 707 ProcessStarter starter(path, | 761 ProcessStarter starter(path, |
| 708 arguments, | 762 arguments, |
| 709 arguments_length, | 763 arguments_length, |
| 710 working_directory, | 764 working_directory, |
| 711 environment, | 765 environment, |
| 712 environment_length, | 766 environment_length, |
| 713 detach, | 767 mode, |
| 714 in, | 768 in, |
| 715 out, | 769 out, |
| 716 err, | 770 err, |
| 717 id, | 771 id, |
| 718 exit_event, | 772 exit_event, |
| 719 os_error_message); | 773 os_error_message); |
| 720 return starter.Start(); | 774 return starter.Start(); |
| 721 } | 775 } |
| 722 | 776 |
| 723 | 777 |
| (...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 959 bzero(&act, sizeof(act)); | 1013 bzero(&act, sizeof(act)); |
| 960 act.sa_handler = SIG_DFL; | 1014 act.sa_handler = SIG_DFL; |
| 961 VOID_NO_RETRY_EXPECTED(sigaction(signal, &act, NULL)); | 1015 VOID_NO_RETRY_EXPECTED(sigaction(signal, &act, NULL)); |
| 962 } | 1016 } |
| 963 } | 1017 } |
| 964 | 1018 |
| 965 } // namespace bin | 1019 } // namespace bin |
| 966 } // namespace dart | 1020 } // namespace dart |
| 967 | 1021 |
| 968 #endif // defined(TARGET_OS_ANDROID) | 1022 #endif // defined(TARGET_OS_ANDROID) |
| OLD | NEW |