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

Unified Diff: runtime/bin/process_macos.cc

Issue 890633002: Add an option for starting a detached process with stdio connected (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Rebased Created 5 years, 11 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/bin/process_linux.cc ('k') | runtime/bin/process_patch.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/bin/process_macos.cc
diff --git a/runtime/bin/process_macos.cc b/runtime/bin/process_macos.cc
index 77ba0a80c07bf0e2cfc306e4d62e44529a08d325..d24a5994ecfdb57ee1ded112f7ee564ea190f252 100644
--- a/runtime/bin/process_macos.cc
+++ b/runtime/bin/process_macos.cc
@@ -237,7 +237,7 @@ class ProcessStarter {
const char* working_directory,
char* environment[],
intptr_t environment_length,
- bool detach,
+ ProcessStartMode mode,
intptr_t* in,
intptr_t* out,
intptr_t* err,
@@ -246,7 +246,7 @@ class ProcessStarter {
char** os_error_message)
: path_(path),
working_directory_(working_directory),
- detach_(detach),
+ mode_(mode),
in_(in),
out_(out),
err_(err),
@@ -307,7 +307,7 @@ class ProcessStarter {
ExitCodeHandler::ProcessStarted();
// Register the child process if not detached.
- if (!detach_) {
+ if (mode_ == kNormal) {
err = RegisterProcess(pid);
if (err != 0) return err;
}
@@ -325,7 +325,7 @@ class ProcessStarter {
// Read the result of executing the child process.
VOID_TEMP_FAILURE_RETRY(close(exec_control_[1]));
exec_control_[1] = -1;
- if (!detach_) {
+ if (mode_ == kNormal) {
err = ReadExecResult();
} else {
err = ReadDetachedExecResult(&pid);
@@ -335,7 +335,7 @@ class ProcessStarter {
// Return error code if any failures.
if (err != 0) {
- if (!detach_) {
+ if (mode_ == kNormal) {
// Since exec() failed, we're not interested in the exit code.
// We close the reading side of the exit code pipe here.
// GetProcessExitCodes will get a broken pipe error when it
@@ -348,7 +348,7 @@ class ProcessStarter {
return err;
}
- if (!detach_) {
+ if (mode_ != kDetached) {
// Connect stdio, stdout and stderr.
FDUtils::SetNonBlocking(read_in_[0]);
*in_ = read_in_[0];
@@ -394,7 +394,7 @@ class ProcessStarter {
FDUtils::SetCloseOnExec(read_in_[0]);
// For detached processes the pipe to connect stderr and stdin are not used.
- if (!detach_) {
+ if (mode_ != kDetached) {
result = TEMP_FAILURE_RETRY(pipe(read_err_));
if (result < 0) {
return CleanupAndReturnError();
@@ -420,10 +420,10 @@ class ProcessStarter {
perror("Failed receiving notification message");
exit(1);
}
- if (detach_) {
- ExecDetachedProcess();
- } else {
+ if (mode_ == kNormal) {
ExecProcess();
+ } else {
+ ExecDetachedProcess();
}
}
@@ -469,14 +469,21 @@ class ProcessStarter {
void ExecDetachedProcess() {
- ASSERT(write_out_[0] == -1);
- ASSERT(write_out_[1] == -1);
- ASSERT(read_err_[0] == -1);
- ASSERT(read_err_[1] == -1);
- // For a detached process the pipe to connect stdout is only used for
- // signaling when to do the first fork.
- VOID_TEMP_FAILURE_RETRY(close(read_in_[0]));
- VOID_TEMP_FAILURE_RETRY(close(read_in_[1]));
+ if (mode_ == kDetached) {
+ ASSERT(write_out_[0] == -1);
+ ASSERT(write_out_[1] == -1);
+ ASSERT(read_err_[0] == -1);
+ ASSERT(read_err_[1] == -1);
+ // For a detached process the pipe to connect stdout is only used for
+ // signaling when to do the first fork.
+ VOID_TEMP_FAILURE_RETRY(close(read_in_[0]));
+ read_in_[0] = -1;
+ VOID_TEMP_FAILURE_RETRY(close(read_in_[1]));
+ read_in_[1] = -1;
+ } else {
+ // Don't close any fds if keeping stdio open to the detached process.
+ ASSERT(mode_ == kDetachedWithStdio);
+ }
// Fork once more to start a new session.
pid_t pid = TEMP_FAILURE_RETRY(fork());
if (pid < 0) {
@@ -491,28 +498,14 @@ class ProcessStarter {
if (pid < 0) {
ReportChildError();
} else if (pid == 0) {
- // Close all open file descriptors except for exec_control_[1].
- int max_fds = sysconf(_SC_OPEN_MAX);
- if (max_fds == -1) max_fds = _POSIX_OPEN_MAX;
- for (int fd = 0; fd < max_fds; fd++) {
- if (fd != exec_control_[1]) {
- VOID_TEMP_FAILURE_RETRY(close(fd));
- }
+ if (mode_ == kDetached) {
+ SetupDetached();
+ } else {
+ SetupDetachedWithStdio();
}
- // Re-open stdin, stdout and stderr and connect them to /dev/null.
- // The loop above should already have closed all of them, so
- // creating new file descriptors should start at STDIN_FILENO.
- int fd = TEMP_FAILURE_RETRY(open("/dev/null", O_RDWR));
- if (fd != STDIN_FILENO) {
- ReportChildError();
- }
- if (TEMP_FAILURE_RETRY(dup2(STDIN_FILENO, STDOUT_FILENO)) !=
- STDOUT_FILENO) {
- ReportChildError();
- }
- if (TEMP_FAILURE_RETRY(dup2(STDIN_FILENO, STDERR_FILENO)) !=
- STDERR_FILENO) {
+ if (working_directory_ != NULL &&
+ TEMP_FAILURE_RETRY(chdir(working_directory_)) == -1) {
ReportChildError();
}
@@ -593,6 +586,67 @@ class ProcessStarter {
}
+ void SetupDetached() {
+ ASSERT(mode_ == kDetached);
+
+ // Close all open file descriptors except for exec_control_[1].
+ int max_fds = sysconf(_SC_OPEN_MAX);
+ if (max_fds == -1) max_fds = _POSIX_OPEN_MAX;
+ for (int fd = 0; fd < max_fds; fd++) {
+ if (fd != exec_control_[1]) {
+ VOID_TEMP_FAILURE_RETRY(close(fd));
+ }
+ }
+
+ // Re-open stdin, stdout and stderr and connect them to /dev/null.
+ // The loop above should already have closed all of them, so
+ // creating new file descriptors should start at STDIN_FILENO.
+ int fd = TEMP_FAILURE_RETRY(open("/dev/null", O_RDWR));
+ if (fd != STDIN_FILENO) {
+ ReportChildError();
+ }
+ if (TEMP_FAILURE_RETRY(dup2(STDIN_FILENO, STDOUT_FILENO)) !=
+ STDOUT_FILENO) {
+ ReportChildError();
+ }
+ if (TEMP_FAILURE_RETRY(dup2(STDIN_FILENO, STDERR_FILENO)) !=
+ STDERR_FILENO) {
+ ReportChildError();
+ }
+ }
+
+ void SetupDetachedWithStdio() {
+ // Close all open file descriptors except for
+ // exec_control_[1], write_out_[0], read_in_[1] and
+ // read_err_[1].
+ int max_fds = sysconf(_SC_OPEN_MAX);
+ if (max_fds == -1) max_fds = _POSIX_OPEN_MAX;
+ for (int fd = 0; fd < max_fds; fd++) {
+ if (fd != exec_control_[1] &&
+ fd != write_out_[0] &&
+ fd != read_in_[1] &&
+ fd != read_err_[1]) {
+ VOID_TEMP_FAILURE_RETRY(close(fd));
+ }
+ }
+
+ if (TEMP_FAILURE_RETRY(dup2(write_out_[0], STDIN_FILENO)) == -1) {
+ ReportChildError();
+ }
+ VOID_TEMP_FAILURE_RETRY(close(write_out_[0]));
+
+ if (TEMP_FAILURE_RETRY(dup2(read_in_[1], STDOUT_FILENO)) == -1) {
+ ReportChildError();
+ }
+ VOID_TEMP_FAILURE_RETRY(close(read_in_[1]));
+
+ if (TEMP_FAILURE_RETRY(dup2(read_err_[1], STDERR_FILENO)) == -1) {
+ ReportChildError();
+ }
+ VOID_TEMP_FAILURE_RETRY(close(read_err_[1]));
+ }
+
+
int CleanupAndReturnError() {
int actual_errno = errno;
// If CleanupAndReturnError is called without an actual errno make
@@ -683,7 +737,7 @@ class ProcessStarter {
const char* path_;
const char* working_directory_;
- bool detach_;
+ ProcessStartMode mode_;
intptr_t* in_;
intptr_t* out_;
intptr_t* err_;
@@ -699,7 +753,7 @@ int Process::Start(const char* path,
const char* working_directory,
char* environment[],
intptr_t environment_length,
- bool detach,
+ ProcessStartMode mode,
intptr_t* in,
intptr_t* out,
intptr_t* err,
@@ -712,7 +766,7 @@ int Process::Start(const char* path,
working_directory,
environment,
environment_length,
- detach,
+ mode,
in,
out,
err,
« no previous file with comments | « runtime/bin/process_linux.cc ('k') | runtime/bin/process_patch.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698