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