| Index: runtime/bin/process_win.cc
|
| diff --git a/runtime/bin/process_win.cc b/runtime/bin/process_win.cc
|
| index 860eee09d44d4c42c88ede19e5cf0005abdd4893..8d6b992f35776c86853d261d0099ff1ee0effa72 100644
|
| --- a/runtime/bin/process_win.cc
|
| +++ b/runtime/bin/process_win.cc
|
| @@ -306,7 +306,7 @@ static void CloseProcessPipes(HANDLE handles1[2],
|
|
|
| static int SetOsErrorMessage(char** os_error_message) {
|
| int error_code = GetLastError();
|
| - static const int kMaxMessageLength = 256;
|
| + const int kMaxMessageLength = 256;
|
| wchar_t message[kMaxMessageLength];
|
| FormatMessageIntoBuffer(error_code, message, kMaxMessageLength);
|
| *os_error_message = StringUtils::WideToUtf8(message);
|
| @@ -314,6 +314,26 @@ static int SetOsErrorMessage(char** os_error_message) {
|
| }
|
|
|
|
|
| +// Open an inheritable handle to NUL.
|
| +static HANDLE OpenNul() {
|
| + SECURITY_ATTRIBUTES inherit_handle;
|
| + inherit_handle.nLength = sizeof(SECURITY_ATTRIBUTES);
|
| + inherit_handle.bInheritHandle = TRUE;
|
| + inherit_handle.lpSecurityDescriptor = NULL;
|
| + HANDLE nul = CreateFile(L"NUL",
|
| + GENERIC_READ | GENERIC_WRITE,
|
| + 0,
|
| + &inherit_handle,
|
| + OPEN_EXISTING,
|
| + 0,
|
| + NULL);
|
| + if (nul == INVALID_HANDLE_VALUE) {
|
| + Log::PrintErr("CloseHandle failed %d\n", GetLastError());
|
| + }
|
| + return nul;
|
| +}
|
| +
|
| +
|
| typedef BOOL (WINAPI *InitProcThreadAttrListFn)(
|
| LPPROC_THREAD_ATTRIBUTE_LIST, DWORD, DWORD, PSIZE_T);
|
|
|
| @@ -385,6 +405,7 @@ int Process::Start(const char* path,
|
| const char* working_directory,
|
| char* environment[],
|
| intptr_t environment_length,
|
| + bool detach,
|
| intptr_t* in,
|
| intptr_t* out,
|
| intptr_t* err,
|
| @@ -405,29 +426,56 @@ int Process::Start(const char* path,
|
| return status;
|
| }
|
|
|
| - if (!CreateProcessPipe(stdin_handles, pipe_names[0], kInheritRead)) {
|
| - int error_code = SetOsErrorMessage(os_error_message);
|
| - CloseProcessPipes(
|
| - stdin_handles, stdout_handles, stderr_handles, exit_handles);
|
| - return error_code;
|
| - }
|
| - if (!CreateProcessPipe(stdout_handles, pipe_names[1], kInheritWrite)) {
|
| - int error_code = SetOsErrorMessage(os_error_message);
|
| - CloseProcessPipes(
|
| - stdin_handles, stdout_handles, stderr_handles, exit_handles);
|
| - return error_code;
|
| - }
|
| - if (!CreateProcessPipe(stderr_handles, pipe_names[2], kInheritWrite)) {
|
| - int error_code = SetOsErrorMessage(os_error_message);
|
| - CloseProcessPipes(
|
| - stdin_handles, stdout_handles, stderr_handles, exit_handles);
|
| - return error_code;
|
| - }
|
| - if (!CreateProcessPipe(exit_handles, pipe_names[3], kInheritNone)) {
|
| - int error_code = SetOsErrorMessage(os_error_message);
|
| - CloseProcessPipes(
|
| - stdin_handles, stdout_handles, stderr_handles, exit_handles);
|
| - return error_code;
|
| + if (!detach) {
|
| + // Open pipes for stdin, stdout, stderr and for communicating the exit
|
| + // code.
|
| + if (!CreateProcessPipe(stdin_handles, pipe_names[0], kInheritRead)) {
|
| + int error_code = SetOsErrorMessage(os_error_message);
|
| + CloseProcessPipes(
|
| + stdin_handles, stdout_handles, stderr_handles, exit_handles);
|
| + return error_code;
|
| + }
|
| + if (!CreateProcessPipe(stdout_handles, pipe_names[1], kInheritWrite)) {
|
| + int error_code = SetOsErrorMessage(os_error_message);
|
| + CloseProcessPipes(
|
| + stdin_handles, stdout_handles, stderr_handles, exit_handles);
|
| + return error_code;
|
| + }
|
| + if (!CreateProcessPipe(stderr_handles, pipe_names[2], kInheritWrite)) {
|
| + int error_code = SetOsErrorMessage(os_error_message);
|
| + CloseProcessPipes(
|
| + stdin_handles, stdout_handles, stderr_handles, exit_handles);
|
| + return error_code;
|
| + }
|
| + if (!CreateProcessPipe(exit_handles, pipe_names[3], kInheritNone)) {
|
| + int error_code = SetOsErrorMessage(os_error_message);
|
| + CloseProcessPipes(
|
| + stdin_handles, stdout_handles, stderr_handles, exit_handles);
|
| + return error_code;
|
| + }
|
| + } else {
|
| + // Open NUL for stdin, stdout and stderr.
|
| + stdin_handles[kReadHandle] = OpenNul();
|
| + if (stdin_handles[kReadHandle] == INVALID_HANDLE_VALUE) {
|
| + int error_code = SetOsErrorMessage(os_error_message);
|
| + CloseProcessPipes(
|
| + stdin_handles, stdout_handles, stderr_handles, exit_handles);
|
| + return error_code;
|
| + }
|
| + stdout_handles[kWriteHandle] = OpenNul();
|
| + if (stdout_handles[kWriteHandle] == INVALID_HANDLE_VALUE) {
|
| + int error_code = SetOsErrorMessage(os_error_message);
|
| + CloseProcessPipes(
|
| + stdin_handles, stdout_handles, stderr_handles, exit_handles);
|
| + return error_code;
|
| + }
|
| + stderr_handles[kWriteHandle] = OpenNul();
|
| + if (stderr_handles[kWriteHandle] == INVALID_HANDLE_VALUE) {
|
| + int error_code = SetOsErrorMessage(os_error_message);
|
| + CloseProcessPipes(
|
| + stdin_handles, stdout_handles, stderr_handles, exit_handles);
|
| + return error_code;
|
| + }
|
| }
|
|
|
| // Setup info structures.
|
| @@ -582,6 +630,9 @@ int Process::Start(const char* path,
|
| // Create process.
|
| DWORD creation_flags =
|
| EXTENDED_STARTUPINFO_PRESENT | CREATE_UNICODE_ENVIRONMENT;
|
| + if (detach) {
|
| + creation_flags |= DETACHED_PROCESS;
|
| + }
|
| BOOL result = CreateProcessW(NULL, // ApplicationName
|
| command_line,
|
| NULL, // ProcessAttributes
|
| @@ -592,7 +643,6 @@ int Process::Start(const char* path,
|
| system_working_directory,
|
| reinterpret_cast<STARTUPINFOW*>(&startup_info),
|
| &process_info);
|
| -
|
| // Deallocate command-line and environment block strings.
|
| delete[] command_line;
|
| delete[] environment_block;
|
| @@ -612,22 +662,24 @@ int Process::Start(const char* path,
|
| return error_code;
|
| }
|
|
|
| - ProcessInfoList::AddProcess(process_info.dwProcessId,
|
| - process_info.hProcess,
|
| - exit_handles[kWriteHandle]);
|
| -
|
| - // Connect the three std streams.
|
| - FileHandle* stdin_handle = new FileHandle(stdin_handles[kWriteHandle]);
|
| CloseHandle(stdin_handles[kReadHandle]);
|
| - FileHandle* stdout_handle = new FileHandle(stdout_handles[kReadHandle]);
|
| CloseHandle(stdout_handles[kWriteHandle]);
|
| - FileHandle* stderr_handle = new FileHandle(stderr_handles[kReadHandle]);
|
| CloseHandle(stderr_handles[kWriteHandle]);
|
| - FileHandle* exit_handle = new FileHandle(exit_handles[kReadHandle]);
|
| - *in = reinterpret_cast<intptr_t>(stdout_handle);
|
| - *out = reinterpret_cast<intptr_t>(stdin_handle);
|
| - *err = reinterpret_cast<intptr_t>(stderr_handle);
|
| - *exit_handler = reinterpret_cast<intptr_t>(exit_handle);
|
| + if (!detach) {
|
| + ProcessInfoList::AddProcess(process_info.dwProcessId,
|
| + process_info.hProcess,
|
| + exit_handles[kWriteHandle]);
|
| +
|
| + // Connect the three std streams.
|
| + FileHandle* stdin_handle = new FileHandle(stdin_handles[kWriteHandle]);
|
| + FileHandle* stdout_handle = new FileHandle(stdout_handles[kReadHandle]);
|
| + FileHandle* stderr_handle = new FileHandle(stderr_handles[kReadHandle]);
|
| + FileHandle* exit_handle = new FileHandle(exit_handles[kReadHandle]);
|
| + *in = reinterpret_cast<intptr_t>(stdout_handle);
|
| + *out = reinterpret_cast<intptr_t>(stdin_handle);
|
| + *err = reinterpret_cast<intptr_t>(stderr_handle);
|
| + *exit_handler = reinterpret_cast<intptr_t>(exit_handle);
|
| + }
|
|
|
| CloseHandle(process_info.hThread);
|
|
|
| @@ -833,16 +885,22 @@ bool Process::Wait(intptr_t pid,
|
|
|
|
|
| bool Process::Kill(intptr_t id, int signal) {
|
| - USE(signal); // signal is not used on windows.
|
| + USE(signal); // signal is not used on Windows.
|
| HANDLE process_handle;
|
| HANDLE wait_handle;
|
| HANDLE exit_pipe;
|
| + // First check the process info list for the process to get a handle to it.
|
| bool success = ProcessInfoList::LookupProcess(id,
|
| &process_handle,
|
| &wait_handle,
|
| &exit_pipe);
|
| - // The process is already dead.
|
| - if (!success) return false;
|
| + // For detached processes we don't have the process registered in the
|
| + // process info list. Try to look it up through the OS.
|
| + if (!success) {
|
| + process_handle = OpenProcess(PROCESS_TERMINATE, FALSE, id);
|
| + // The process is already dead.
|
| + if (process_handle == INVALID_HANDLE_VALUE) return false;
|
| + }
|
| BOOL result = TerminateProcess(process_handle, -1);
|
| return result ? true : false;
|
| }
|
|
|