Chromium Code Reviews| 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_WINDOWS) | 6 #if defined(TARGET_OS_WINDOWS) |
| 7 | 7 |
| 8 #include "bin/process.h" | |
| 9 | |
| 8 #include <process.h> // NOLINT | 10 #include <process.h> // NOLINT |
| 9 | 11 |
| 10 #include "bin/builtin.h" | 12 #include "bin/builtin.h" |
| 11 #include "bin/dartutils.h" | 13 #include "bin/dartutils.h" |
| 12 #include "bin/process.h" | |
| 13 #include "bin/eventhandler.h" | 14 #include "bin/eventhandler.h" |
| 14 #include "bin/lockers.h" | 15 #include "bin/lockers.h" |
| 15 #include "bin/log.h" | 16 #include "bin/log.h" |
| 16 #include "bin/socket.h" | 17 #include "bin/socket.h" |
| 17 #include "bin/thread.h" | 18 #include "bin/thread.h" |
| 18 #include "bin/utils.h" | 19 #include "bin/utils.h" |
| 19 #include "bin/utils_win.h" | 20 #include "bin/utils_win.h" |
| 20 | 21 |
| 21 | |
| 22 namespace dart { | 22 namespace dart { |
| 23 namespace bin { | 23 namespace bin { |
| 24 | 24 |
| 25 static const int kReadHandle = 0; | 25 static const int kReadHandle = 0; |
| 26 static const int kWriteHandle = 1; | 26 static const int kWriteHandle = 1; |
| 27 | 27 |
| 28 | 28 |
| 29 // ProcessInfo is used to map a process id to the process handle, | 29 // ProcessInfo is used to map a process id to the process handle, |
| 30 // wait handle for registered exit code event and the pipe used to | 30 // wait handle for registered exit code event and the pipe used to |
| 31 // communicate the exit code of the process to Dart. | 31 // communicate the exit code of the process to Dart. |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 65 DWORD process_id_; | 65 DWORD process_id_; |
| 66 // Process handle. | 66 // Process handle. |
| 67 HANDLE process_handle_; | 67 HANDLE process_handle_; |
| 68 // Wait handle identifying the exit-code wait operation registered | 68 // Wait handle identifying the exit-code wait operation registered |
| 69 // with RegisterWaitForSingleObject. | 69 // with RegisterWaitForSingleObject. |
| 70 HANDLE wait_handle_; | 70 HANDLE wait_handle_; |
| 71 // File descriptor for pipe to report exit code. | 71 // File descriptor for pipe to report exit code. |
| 72 HANDLE exit_pipe_; | 72 HANDLE exit_pipe_; |
| 73 // Link to next ProcessInfo object in the singly-linked list. | 73 // Link to next ProcessInfo object in the singly-linked list. |
| 74 ProcessInfo* next_; | 74 ProcessInfo* next_; |
| 75 | |
| 76 DISALLOW_COPY_AND_ASSIGN(ProcessInfo); | |
| 75 }; | 77 }; |
| 76 | 78 |
| 77 | 79 |
| 78 // Singly-linked list of ProcessInfo objects for all active processes | 80 // Singly-linked list of ProcessInfo objects for all active processes |
| 79 // started from Dart. | 81 // started from Dart. |
| 80 class ProcessInfoList { | 82 class ProcessInfoList { |
| 81 public: | 83 public: |
| 82 static void AddProcess(DWORD pid, HANDLE handle, HANDLE pipe) { | 84 static void AddProcess(DWORD pid, HANDLE handle, HANDLE pipe) { |
| 83 // Register a callback to extract the exit code, when the process | 85 // Register a callback to extract the exit code, when the process |
| 84 // is signaled. The callback runs in a independent thread from the OS pool. | 86 // is signaled. The callback runs in a independent thread from the OS pool. |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 136 } | 138 } |
| 137 prev = current; | 139 prev = current; |
| 138 current = current->next(); | 140 current = current->next(); |
| 139 } | 141 } |
| 140 } | 142 } |
| 141 | 143 |
| 142 private: | 144 private: |
| 143 // Callback called when an exit code is available from one of the | 145 // Callback called when an exit code is available from one of the |
| 144 // processes in the list. | 146 // processes in the list. |
| 145 static void CALLBACK ExitCodeCallback(PVOID data, BOOLEAN timed_out) { | 147 static void CALLBACK ExitCodeCallback(PVOID data, BOOLEAN timed_out) { |
| 146 if (timed_out) return; | 148 if (timed_out) { |
| 149 return; | |
| 150 } | |
| 147 DWORD pid = reinterpret_cast<DWORD>(data); | 151 DWORD pid = reinterpret_cast<DWORD>(data); |
| 148 HANDLE handle; | 152 HANDLE handle; |
| 149 HANDLE wait_handle; | 153 HANDLE wait_handle; |
| 150 HANDLE exit_pipe; | 154 HANDLE exit_pipe; |
| 151 bool success = LookupProcess(pid, &handle, &wait_handle, &exit_pipe); | 155 bool success = LookupProcess(pid, &handle, &wait_handle, &exit_pipe); |
| 152 if (!success) { | 156 if (!success) { |
| 153 FATAL("Failed to lookup process in list of active processes"); | 157 FATAL("Failed to lookup process in list of active processes"); |
| 154 } | 158 } |
| 155 // Unregister the event in a non-blocking way. | 159 // Unregister the event in a non-blocking way. |
| 156 BOOL ok = UnregisterWait(wait_handle); | 160 BOOL ok = UnregisterWait(wait_handle); |
| 157 if (!ok && GetLastError() != ERROR_IO_PENDING) { | 161 if (!ok && (GetLastError() != ERROR_IO_PENDING)) { |
| 158 FATAL("Failed unregistering wait operation"); | 162 FATAL("Failed unregistering wait operation"); |
| 159 } | 163 } |
| 160 // Get and report the exit code to Dart. | 164 // Get and report the exit code to Dart. |
| 161 int exit_code; | 165 int exit_code; |
| 162 ok = GetExitCodeProcess(handle, | 166 ok = GetExitCodeProcess(handle, reinterpret_cast<DWORD*>(&exit_code)); |
| 163 reinterpret_cast<DWORD*>(&exit_code)); | |
| 164 if (!ok) { | 167 if (!ok) { |
| 165 FATAL1("GetExitCodeProcess failed %d\n", GetLastError()); | 168 FATAL1("GetExitCodeProcess failed %d\n", GetLastError()); |
| 166 } | 169 } |
| 167 int negative = 0; | 170 int negative = 0; |
| 168 if (exit_code < 0) { | 171 if (exit_code < 0) { |
| 169 exit_code = abs(exit_code); | 172 exit_code = abs(exit_code); |
| 170 negative = 1; | 173 negative = 1; |
| 171 } | 174 } |
| 172 int message[2] = { exit_code, negative }; | 175 int message[2] = { exit_code, negative }; |
| 173 DWORD written; | 176 DWORD written; |
| 174 ok = WriteFile(exit_pipe, message, sizeof(message), &written, NULL); | 177 ok = WriteFile(exit_pipe, message, sizeof(message), &written, NULL); |
| 175 // If the process has been closed, the read end of the exit | 178 // If the process has been closed, the read end of the exit |
| 176 // pipe has been closed. It is therefore not a problem that | 179 // pipe has been closed. It is therefore not a problem that |
| 177 // WriteFile fails with a closed pipe error | 180 // WriteFile fails with a closed pipe error |
| 178 // (ERROR_NO_DATA). Other errors should not happen. | 181 // (ERROR_NO_DATA). Other errors should not happen. |
| 179 if (ok && written != sizeof(message)) { | 182 if (ok && (written != sizeof(message))) { |
| 180 FATAL("Failed to write entire process exit message"); | 183 FATAL("Failed to write entire process exit message"); |
| 181 } else if (!ok && GetLastError() != ERROR_NO_DATA) { | 184 } else if (!ok && (GetLastError() != ERROR_NO_DATA)) { |
| 182 FATAL1("Failed to write exit code: %d", GetLastError()); | 185 FATAL1("Failed to write exit code: %d", GetLastError()); |
| 183 } | 186 } |
| 184 // Remove the process from the list of active processes. | 187 // Remove the process from the list of active processes. |
| 185 RemoveProcess(pid); | 188 RemoveProcess(pid); |
| 186 } | 189 } |
| 187 | 190 |
| 188 // Linked list of ProcessInfo objects for all active processes | 191 // Linked list of ProcessInfo objects for all active processes |
| 189 // started from Dart code. | 192 // started from Dart code. |
| 190 static ProcessInfo* active_processes_; | 193 static ProcessInfo* active_processes_; |
| 191 // Mutex protecting all accesses to the linked list of active | 194 // Mutex protecting all accesses to the linked list of active |
| 192 // processes. | 195 // processes. |
| 193 static Mutex* mutex_; | 196 static Mutex* mutex_; |
| 197 | |
| 198 DISALLOW_ALLOCATION(); | |
| 199 DISALLOW_IMPLICIT_CONSTRUCTORS(ProcessInfoList); | |
| 194 }; | 200 }; |
| 195 | 201 |
| 196 | 202 |
| 197 ProcessInfo* ProcessInfoList::active_processes_ = NULL; | 203 ProcessInfo* ProcessInfoList::active_processes_ = NULL; |
| 198 Mutex* ProcessInfoList::mutex_ = new Mutex(); | 204 Mutex* ProcessInfoList::mutex_ = new Mutex(); |
| 199 | 205 |
| 200 | 206 |
| 201 // Types of pipes to create. | 207 // Types of pipes to create. |
| 202 enum NamedPipeType { | 208 enum NamedPipeType { |
| 203 kInheritRead, | 209 kInheritRead, |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 242 0, | 248 0, |
| 243 &inherit_handle, | 249 &inherit_handle, |
| 244 OPEN_EXISTING, | 250 OPEN_EXISTING, |
| 245 FILE_READ_ATTRIBUTES | FILE_FLAG_OVERLAPPED, | 251 FILE_READ_ATTRIBUTES | FILE_FLAG_OVERLAPPED, |
| 246 NULL); | 252 NULL); |
| 247 if (handles[kReadHandle] == INVALID_HANDLE_VALUE) { | 253 if (handles[kReadHandle] == INVALID_HANDLE_VALUE) { |
| 248 Log::PrintErr("CreateFile failed %d\n", GetLastError()); | 254 Log::PrintErr("CreateFile failed %d\n", GetLastError()); |
| 249 return false; | 255 return false; |
| 250 } | 256 } |
| 251 } else { | 257 } else { |
| 252 ASSERT(type == kInheritWrite || type == kInheritNone); | 258 ASSERT((type == kInheritWrite) || (type == kInheritNone)); |
| 253 handles[kReadHandle] = | 259 handles[kReadHandle] = |
| 254 CreateNamedPipeW(pipe_name, | 260 CreateNamedPipeW(pipe_name, |
| 255 PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, | 261 PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, |
| 256 PIPE_TYPE_BYTE | PIPE_WAIT, | 262 PIPE_TYPE_BYTE | PIPE_WAIT, |
| 257 1, // Number of pipes | 263 1, // Number of pipes |
| 258 1024, // Out buffer size | 264 1024, // Out buffer size |
| 259 1024, // In buffer size | 265 1024, // In buffer size |
| 260 0, // Timeout in ms | 266 0, // Timeout in ms |
| 261 NULL); | 267 NULL); |
| 262 | 268 |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 350 static UpdateProcThreadAttrFn update_proc_thread_attr = NULL; | 356 static UpdateProcThreadAttrFn update_proc_thread_attr = NULL; |
| 351 static DeleteProcThreadAttrListFn delete_proc_thread_attr_list = NULL; | 357 static DeleteProcThreadAttrListFn delete_proc_thread_attr_list = NULL; |
| 352 | 358 |
| 353 | 359 |
| 354 static bool EnsureInitialized() { | 360 static bool EnsureInitialized() { |
| 355 static bool load_attempted = false; | 361 static bool load_attempted = false; |
| 356 static Mutex* mutex = new Mutex(); | 362 static Mutex* mutex = new Mutex(); |
| 357 HMODULE kernel32_module = GetModuleHandleW(L"kernel32.dll"); | 363 HMODULE kernel32_module = GetModuleHandleW(L"kernel32.dll"); |
| 358 if (!load_attempted) { | 364 if (!load_attempted) { |
| 359 MutexLocker locker(mutex); | 365 MutexLocker locker(mutex); |
| 360 if (load_attempted) return delete_proc_thread_attr_list != NULL; | 366 if (load_attempted) { |
| 367 return (delete_proc_thread_attr_list != NULL); | |
| 368 } | |
| 361 init_proc_thread_attr_list = reinterpret_cast<InitProcThreadAttrListFn>( | 369 init_proc_thread_attr_list = reinterpret_cast<InitProcThreadAttrListFn>( |
| 362 GetProcAddress(kernel32_module, "InitializeProcThreadAttributeList")); | 370 GetProcAddress(kernel32_module, "InitializeProcThreadAttributeList")); |
| 363 update_proc_thread_attr = | 371 update_proc_thread_attr = reinterpret_cast<UpdateProcThreadAttrFn>( |
| 364 reinterpret_cast<UpdateProcThreadAttrFn>( | 372 GetProcAddress(kernel32_module, "UpdateProcThreadAttribute")); |
| 365 GetProcAddress(kernel32_module, "UpdateProcThreadAttribute")); | |
| 366 delete_proc_thread_attr_list = reinterpret_cast<DeleteProcThreadAttrListFn>( | 373 delete_proc_thread_attr_list = reinterpret_cast<DeleteProcThreadAttrListFn>( |
| 367 reinterpret_cast<DeleteProcThreadAttrListFn>( | 374 GetProcAddress(kernel32_module, "DeleteProcThreadAttributeList")); |
| 368 GetProcAddress(kernel32_module, "DeleteProcThreadAttributeList"))); | |
| 369 load_attempted = true; | 375 load_attempted = true; |
| 370 return delete_proc_thread_attr_list != NULL; | 376 return (delete_proc_thread_attr_list != NULL); |
| 371 } | 377 } |
| 372 return delete_proc_thread_attr_list != NULL; | 378 return (delete_proc_thread_attr_list != NULL); |
| 373 } | 379 } |
| 374 | 380 |
| 375 | 381 |
| 376 const int kMaxPipeNameSize = 80; | 382 const int kMaxPipeNameSize = 80; |
| 377 template<int Count> | 383 template<int Count> |
| 378 static int GenerateNames(wchar_t pipe_names[Count][kMaxPipeNameSize]) { | 384 static int GenerateNames(wchar_t pipe_names[Count][kMaxPipeNameSize]) { |
| 379 UUID uuid; | 385 UUID uuid; |
| 380 RPC_STATUS status = UuidCreateSequential(&uuid); | 386 RPC_STATUS status = UuidCreateSequential(&uuid); |
| 381 if (status != RPC_S_OK && status != RPC_S_UUID_LOCAL_ONLY) { | 387 if ((status != RPC_S_OK) && (status != RPC_S_UUID_LOCAL_ONLY)) { |
| 382 return status; | 388 return status; |
| 383 } | 389 } |
| 384 RPC_WSTR uuid_string; | 390 RPC_WSTR uuid_string; |
| 385 status = UuidToStringW(&uuid, &uuid_string); | 391 status = UuidToStringW(&uuid, &uuid_string); |
| 386 if (status != RPC_S_OK) { | 392 if (status != RPC_S_OK) { |
| 387 return status; | 393 return status; |
| 388 } | 394 } |
| 389 for (int i = 0; i < Count; i++) { | 395 for (int i = 0; i < Count; i++) { |
| 390 static const wchar_t* prefix = L"\\\\.\\Pipe\\dart"; | 396 static const wchar_t* prefix = L"\\\\.\\Pipe\\dart"; |
| 391 _snwprintf(pipe_names[i], | 397 _snwprintf(pipe_names[i], |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 444 | 450 |
| 445 // Compute command-line length. | 451 // Compute command-line length. |
| 446 int command_line_length = wcslen(system_path); | 452 int command_line_length = wcslen(system_path); |
| 447 for (int i = 0; i < arguments_length; i++) { | 453 for (int i = 0; i < arguments_length; i++) { |
| 448 command_line_length += wcslen(system_arguments[i]); | 454 command_line_length += wcslen(system_arguments[i]); |
| 449 } | 455 } |
| 450 // Account for null termination and one space per argument. | 456 // Account for null termination and one space per argument. |
| 451 command_line_length += arguments_length + 1; | 457 command_line_length += arguments_length + 1; |
| 452 | 458 |
| 453 // Put together command-line string. | 459 // Put together command-line string. |
| 454 command_line_ = new wchar_t[command_line_length]; | 460 command_line_ = reinterpret_cast<wchar_t*>(Dart_ScopeAllocate( |
|
zra
2016/03/15 18:12:29
Changed to scope allocated.
| |
| 461 command_line_length * sizeof(*command_line_))); | |
| 455 int len = 0; | 462 int len = 0; |
| 456 int remaining = command_line_length; | 463 int remaining = command_line_length; |
| 457 int written = | 464 int written = |
| 458 _snwprintf(command_line_ + len, remaining, L"%s", system_path); | 465 _snwprintf(command_line_ + len, remaining, L"%s", system_path); |
| 459 len += written; | 466 len += written; |
| 460 remaining -= written; | 467 remaining -= written; |
| 461 ASSERT(remaining >= 0); | 468 ASSERT(remaining >= 0); |
| 462 for (int i = 0; i < arguments_length; i++) { | 469 for (int i = 0; i < arguments_length; i++) { |
| 463 written = | 470 written = _snwprintf( |
| 464 _snwprintf( | 471 command_line_ + len, remaining, L" %s", system_arguments[i]); |
| 465 command_line_ + len, remaining, L" %s", system_arguments[i]); | |
| 466 len += written; | 472 len += written; |
| 467 remaining -= written; | 473 remaining -= written; |
| 468 ASSERT(remaining >= 0); | 474 ASSERT(remaining >= 0); |
| 469 } | 475 } |
| 470 | 476 |
| 471 // Create environment block if an environment is supplied. | 477 // Create environment block if an environment is supplied. |
| 472 environment_block_ = NULL; | 478 environment_block_ = NULL; |
| 473 if (environment != NULL) { | 479 if (environment != NULL) { |
| 474 wchar_t** system_environment; | 480 wchar_t** system_environment; |
| 475 system_environment = reinterpret_cast<wchar_t**>( | 481 system_environment = reinterpret_cast<wchar_t**>( |
| 476 Dart_ScopeAllocate(environment_length * sizeof(*system_environment))); | 482 Dart_ScopeAllocate(environment_length * sizeof(*system_environment))); |
| 477 // Convert environment strings to system strings. | 483 // Convert environment strings to system strings. |
| 478 for (intptr_t i = 0; i < environment_length; i++) { | 484 for (intptr_t i = 0; i < environment_length; i++) { |
| 479 system_environment[i] = StringUtilsWin::Utf8ToWide(environment[i]); | 485 system_environment[i] = StringUtilsWin::Utf8ToWide(environment[i]); |
| 480 } | 486 } |
| 481 | 487 |
| 482 // An environment block is a sequence of zero-terminated strings | 488 // An environment block is a sequence of zero-terminated strings |
| 483 // followed by a block-terminating zero char. | 489 // followed by a block-terminating zero char. |
| 484 intptr_t block_size = 1; | 490 intptr_t block_size = 1; |
| 485 for (intptr_t i = 0; i < environment_length; i++) { | 491 for (intptr_t i = 0; i < environment_length; i++) { |
| 486 block_size += wcslen(system_environment[i]) + 1; | 492 block_size += wcslen(system_environment[i]) + 1; |
| 487 } | 493 } |
| 488 environment_block_ = new wchar_t[block_size]; | 494 environment_block_ = reinterpret_cast<wchar_t*>(Dart_ScopeAllocate( |
|
zra
2016/03/15 18:12:29
ditto.
| |
| 495 block_size * sizeof(*environment_block_))); | |
| 489 intptr_t block_index = 0; | 496 intptr_t block_index = 0; |
| 490 for (intptr_t i = 0; i < environment_length; i++) { | 497 for (intptr_t i = 0; i < environment_length; i++) { |
| 491 intptr_t len = wcslen(system_environment[i]); | 498 intptr_t len = wcslen(system_environment[i]); |
| 492 intptr_t result = _snwprintf(environment_block_ + block_index, | 499 intptr_t result = _snwprintf(environment_block_ + block_index, |
| 493 len, | 500 len, |
| 494 L"%s", | 501 L"%s", |
| 495 system_environment[i]); | 502 system_environment[i]); |
| 496 ASSERT(result == len); | 503 ASSERT(result == len); |
| 497 block_index += len; | 504 block_index += len; |
| 498 environment_block_[block_index++] = '\0'; | 505 environment_block_[block_index++] = '\0'; |
| 499 } | 506 } |
| 500 // Block-terminating zero char. | 507 // Block-terminating zero char. |
| 501 environment_block_[block_index++] = '\0'; | 508 environment_block_[block_index++] = '\0'; |
| 502 ASSERT(block_index == block_size); | 509 ASSERT(block_index == block_size); |
| 503 } | 510 } |
| 504 | 511 |
| 505 system_working_directory_ = NULL; | 512 system_working_directory_ = NULL; |
| 506 if (working_directory_ != NULL) { | 513 if (working_directory_ != NULL) { |
| 507 system_working_directory_ = | 514 system_working_directory_ = |
| 508 StringUtilsWin::Utf8ToWide(working_directory_); | 515 StringUtilsWin::Utf8ToWide(working_directory_); |
| 509 } | 516 } |
| 510 | 517 |
| 511 attribute_list_ = NULL; | 518 attribute_list_ = NULL; |
| 512 } | 519 } |
| 513 | 520 |
| 514 | 521 |
| 515 ~ProcessStarter() { | 522 ~ProcessStarter() { |
| 516 // Deallocate command-line and environment block strings. | |
| 517 delete[] command_line_; | |
| 518 delete[] environment_block_; | |
| 519 if (attribute_list_ != NULL) { | 523 if (attribute_list_ != NULL) { |
| 520 delete_proc_thread_attr_list(attribute_list_); | 524 delete_proc_thread_attr_list(attribute_list_); |
| 521 free(attribute_list_); | |
| 522 } | 525 } |
| 523 } | 526 } |
| 524 | 527 |
| 525 | 528 |
| 526 int Start() { | 529 int Start() { |
| 527 // Create pipes required. | 530 // Create pipes required. |
| 528 int err = CreatePipes(); | 531 int err = CreatePipes(); |
| 529 if (err != 0) return err; | 532 if (err != 0) { |
| 533 return err; | |
| 534 } | |
| 530 | 535 |
| 531 // Setup info structures. | 536 // Setup info structures. |
| 532 STARTUPINFOEXW startup_info; | 537 STARTUPINFOEXW startup_info; |
| 533 ZeroMemory(&startup_info, sizeof(startup_info)); | 538 ZeroMemory(&startup_info, sizeof(startup_info)); |
| 534 startup_info.StartupInfo.cb = sizeof(startup_info); | 539 startup_info.StartupInfo.cb = sizeof(startup_info); |
| 535 startup_info.StartupInfo.hStdInput = stdin_handles_[kReadHandle]; | 540 startup_info.StartupInfo.hStdInput = stdin_handles_[kReadHandle]; |
| 536 startup_info.StartupInfo.hStdOutput = stdout_handles_[kWriteHandle]; | 541 startup_info.StartupInfo.hStdOutput = stdout_handles_[kWriteHandle]; |
| 537 startup_info.StartupInfo.hStdError = stderr_handles_[kWriteHandle]; | 542 startup_info.StartupInfo.hStdError = stderr_handles_[kWriteHandle]; |
| 538 startup_info.StartupInfo.dwFlags = STARTF_USESTDHANDLES; | 543 startup_info.StartupInfo.dwFlags = STARTF_USESTDHANDLES; |
| 539 | 544 |
| 540 bool supports_proc_thread_attr_lists = EnsureInitialized(); | 545 bool supports_proc_thread_attr_lists = EnsureInitialized(); |
| 541 if (supports_proc_thread_attr_lists) { | 546 if (supports_proc_thread_attr_lists) { |
| 542 // Setup the handles to inherit. We only want to inherit the three handles | 547 // Setup the handles to inherit. We only want to inherit the three handles |
| 543 // for stdin, stdout and stderr. | 548 // for stdin, stdout and stderr. |
| 544 SIZE_T size = 0; | 549 SIZE_T size = 0; |
| 545 // The call to determine the size of an attribute list always fails with | 550 // The call to determine the size of an attribute list always fails with |
| 546 // ERROR_INSUFFICIENT_BUFFER and that error should be ignored. | 551 // ERROR_INSUFFICIENT_BUFFER and that error should be ignored. |
| 547 if (!init_proc_thread_attr_list(NULL, 1, 0, &size) && | 552 if (!init_proc_thread_attr_list(NULL, 1, 0, &size) && |
| 548 GetLastError() != ERROR_INSUFFICIENT_BUFFER) { | 553 (GetLastError() != ERROR_INSUFFICIENT_BUFFER)) { |
| 549 return CleanupAndReturnError(); | 554 return CleanupAndReturnError(); |
| 550 } | 555 } |
| 551 attribute_list_ = | 556 attribute_list_ = reinterpret_cast<LPPROC_THREAD_ATTRIBUTE_LIST>( |
|
zra
2016/03/15 18:12:29
ditto.
| |
| 552 reinterpret_cast<LPPROC_THREAD_ATTRIBUTE_LIST>(malloc(size)); | 557 Dart_ScopeAllocate(size)); |
| 553 ZeroMemory(attribute_list_, size); | 558 ZeroMemory(attribute_list_, size); |
| 554 if (!init_proc_thread_attr_list(attribute_list_, 1, 0, &size)) { | 559 if (!init_proc_thread_attr_list(attribute_list_, 1, 0, &size)) { |
| 555 return CleanupAndReturnError(); | 560 return CleanupAndReturnError(); |
| 556 } | 561 } |
| 557 static const int kNumInheritedHandles = 3; | 562 static const int kNumInheritedHandles = 3; |
| 558 HANDLE inherited_handles[kNumInheritedHandles] = | 563 HANDLE inherited_handles[kNumInheritedHandles] = |
| 559 { stdin_handles_[kReadHandle], | 564 { stdin_handles_[kReadHandle], |
| 560 stdout_handles_[kWriteHandle], | 565 stdout_handles_[kWriteHandle], |
| 561 stderr_handles_[kWriteHandle] }; | 566 stderr_handles_[kWriteHandle] }; |
| 562 if (!update_proc_thread_attr(attribute_list_, | 567 if (!update_proc_thread_attr(attribute_list_, |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 643 !CreateProcessPipe(stderr_handles_, pipe_names[2], kInheritWrite)) { | 648 !CreateProcessPipe(stderr_handles_, pipe_names[2], kInheritWrite)) { |
| 644 return CleanupAndReturnError(); | 649 return CleanupAndReturnError(); |
| 645 } | 650 } |
| 646 // Only open exit code pipe for non detached processes. | 651 // Only open exit code pipe for non detached processes. |
| 647 if (mode_ == kNormal) { | 652 if (mode_ == kNormal) { |
| 648 if (!CreateProcessPipe(exit_handles_, pipe_names[3], kInheritNone)) { | 653 if (!CreateProcessPipe(exit_handles_, pipe_names[3], kInheritNone)) { |
| 649 return CleanupAndReturnError(); | 654 return CleanupAndReturnError(); |
| 650 } | 655 } |
| 651 } | 656 } |
| 652 } else { | 657 } else { |
| 653 // Open NUL for stdin, stdout and stderr. | 658 // Open NUL for stdin, stdout, and stderr. |
| 654 if ((stdin_handles_[kReadHandle] = OpenNul()) == INVALID_HANDLE_VALUE || | 659 stdin_handles_[kReadHandle] = OpenNul(); |
| 655 (stdout_handles_[kWriteHandle] = OpenNul()) == INVALID_HANDLE_VALUE || | 660 if (stdin_handles_[kReadHandle] == INVALID_HANDLE_VALUE) { |
| 656 (stderr_handles_[kWriteHandle] = OpenNul()) == INVALID_HANDLE_VALUE) { | 661 return CleanupAndReturnError(); |
| 662 } | |
| 663 | |
| 664 stdout_handles_[kWriteHandle] = OpenNul(); | |
| 665 if (stdout_handles_[kWriteHandle] == INVALID_HANDLE_VALUE) { | |
| 666 return CleanupAndReturnError(); | |
| 667 } | |
| 668 | |
| 669 stderr_handles_[kWriteHandle] = OpenNul(); | |
| 670 if (stderr_handles_[kWriteHandle] == INVALID_HANDLE_VALUE) { | |
| 657 return CleanupAndReturnError(); | 671 return CleanupAndReturnError(); |
| 658 } | 672 } |
| 659 } | 673 } |
| 660 return 0; | 674 return 0; |
| 661 } | 675 } |
| 662 | 676 |
| 663 | 677 |
| 664 int CleanupAndReturnError() { | 678 int CleanupAndReturnError() { |
| 665 int error_code = SetOsErrorMessage(os_error_message_); | 679 int error_code = SetOsErrorMessage(os_error_message_); |
| 666 CloseProcessPipes( | 680 CloseProcessPipes( |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 681 | 695 |
| 682 const char* path_; | 696 const char* path_; |
| 683 const char* working_directory_; | 697 const char* working_directory_; |
| 684 ProcessStartMode mode_; | 698 ProcessStartMode mode_; |
| 685 intptr_t* in_; | 699 intptr_t* in_; |
| 686 intptr_t* out_; | 700 intptr_t* out_; |
| 687 intptr_t* err_; | 701 intptr_t* err_; |
| 688 intptr_t* id_; | 702 intptr_t* id_; |
| 689 intptr_t* exit_handler_; | 703 intptr_t* exit_handler_; |
| 690 char** os_error_message_; | 704 char** os_error_message_; |
| 705 | |
| 706 private: | |
| 707 DISALLOW_ALLOCATION(); | |
| 708 DISALLOW_IMPLICIT_CONSTRUCTORS(ProcessStarter); | |
| 691 }; | 709 }; |
| 692 | 710 |
| 693 | 711 |
| 694 int Process::Start(const char* path, | 712 int Process::Start(const char* path, |
| 695 char* arguments[], | 713 char* arguments[], |
| 696 intptr_t arguments_length, | 714 intptr_t arguments_length, |
| 697 const char* working_directory, | 715 const char* working_directory, |
| 698 char* environment[], | 716 char* environment[], |
| 699 intptr_t environment_length, | 717 intptr_t environment_length, |
| 700 ProcessStartMode mode, | 718 ProcessStartMode mode, |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 731 ASSERT(read_pending_ == true); | 749 ASSERT(read_pending_ == true); |
| 732 data_size_ += size; | 750 data_size_ += size; |
| 733 free_size_ -= size; | 751 free_size_ -= size; |
| 734 ASSERT(free_size_ >= 0); | 752 ASSERT(free_size_ >= 0); |
| 735 read_pending_ = false; | 753 read_pending_ = false; |
| 736 } | 754 } |
| 737 | 755 |
| 738 // The access to the read buffer for overlapped read. | 756 // The access to the read buffer for overlapped read. |
| 739 void GetReadBuffer(uint8_t** buffer, intptr_t* size) { | 757 void GetReadBuffer(uint8_t** buffer, intptr_t* size) { |
| 740 ASSERT(!read_pending_); | 758 ASSERT(!read_pending_); |
| 741 if (free_size_ == 0) Allocate(); | 759 if (free_size_ == 0) { |
| 760 Allocate(); | |
| 761 } | |
| 742 ASSERT(free_size_ > 0); | 762 ASSERT(free_size_ > 0); |
| 743 ASSERT(free_size_ <= kBufferSize); | 763 ASSERT(free_size_ <= kBufferSize); |
| 744 *buffer = FreeSpaceAddress(); | 764 *buffer = FreeSpaceAddress(); |
| 745 *size = free_size_; | 765 *size = free_size_; |
| 746 read_pending_ = true; | 766 read_pending_ = true; |
| 747 } | 767 } |
| 748 | 768 |
| 749 intptr_t GetDataSize() { | 769 intptr_t GetDataSize() { |
| 750 return data_size_; | 770 return data_size_; |
| 751 } | 771 } |
| 752 | 772 |
| 753 uint8_t* GetFirstDataBuffer() { | 773 uint8_t* GetFirstDataBuffer() { |
| 754 ASSERT(head_ != NULL); | 774 ASSERT(head_ != NULL); |
| 755 ASSERT(head_ == tail_); | 775 ASSERT(head_ == tail_); |
| 756 ASSERT(data_size_ <= kBufferSize); | 776 ASSERT(data_size_ <= kBufferSize); |
| 757 return head_->data_; | 777 return head_->data_; |
| 758 } | 778 } |
| 759 | 779 |
| 760 void FreeDataBuffer() { | 780 void FreeDataBuffer() { |
| 761 Free(); | 781 Free(); |
| 762 } | 782 } |
| 763 | 783 |
| 764 private: | 784 private: |
| 765 bool read_pending_; | 785 bool read_pending_; |
| 786 | |
| 787 DISALLOW_COPY_AND_ASSIGN(BufferList); | |
| 766 }; | 788 }; |
| 767 | 789 |
| 768 | 790 |
| 769 class OverlappedHandle { | 791 class OverlappedHandle { |
| 770 public: | 792 public: |
| 793 OverlappedHandle() {} | |
| 794 | |
| 771 void Init(HANDLE handle, HANDLE event) { | 795 void Init(HANDLE handle, HANDLE event) { |
| 772 handle_ = handle; | 796 handle_ = handle; |
| 773 event_ = event; | 797 event_ = event; |
| 774 ClearOverlapped(); | 798 ClearOverlapped(); |
| 775 } | 799 } |
| 776 | 800 |
| 777 bool HasEvent(HANDLE event) { | 801 bool HasEvent(HANDLE event) { |
| 778 return event_ == event; | 802 return (event_ == event); |
| 779 } | 803 } |
| 780 | 804 |
| 781 bool Read() { | 805 bool Read() { |
| 782 // Get the data read as a result of a completed overlapped operation. | 806 // Get the data read as a result of a completed overlapped operation. |
| 783 if (overlapped_.InternalHigh > 0) { | 807 if (overlapped_.InternalHigh > 0) { |
| 784 buffer_.DataIsRead(overlapped_.InternalHigh); | 808 buffer_.DataIsRead(overlapped_.InternalHigh); |
| 785 } else { | 809 } else { |
| 786 buffer_.DataIsRead(0); | 810 buffer_.DataIsRead(0); |
| 787 } | 811 } |
| 788 | 812 |
| 789 // Keep reading until error or pending operation. | 813 // Keep reading until error or pending operation. |
| 790 while (true) { | 814 while (true) { |
| 791 ClearOverlapped(); | 815 ClearOverlapped(); |
| 792 uint8_t* buffer; | 816 uint8_t* buffer; |
| 793 intptr_t buffer_size; | 817 intptr_t buffer_size; |
| 794 buffer_.GetReadBuffer(&buffer, &buffer_size); | 818 buffer_.GetReadBuffer(&buffer, &buffer_size); |
| 795 BOOL ok = ReadFile(handle_, buffer, buffer_size, NULL, &overlapped_); | 819 BOOL ok = ReadFile(handle_, buffer, buffer_size, NULL, &overlapped_); |
| 796 if (!ok) return GetLastError() == ERROR_IO_PENDING; | 820 if (!ok) { |
| 821 return (GetLastError() == ERROR_IO_PENDING); | |
| 822 } | |
| 797 buffer_.DataIsRead(overlapped_.InternalHigh); | 823 buffer_.DataIsRead(overlapped_.InternalHigh); |
| 798 } | 824 } |
| 799 } | 825 } |
| 800 | 826 |
| 801 Dart_Handle GetData() { | 827 Dart_Handle GetData() { |
| 802 return buffer_.GetData(); | 828 return buffer_.GetData(); |
| 803 } | 829 } |
| 804 | 830 |
| 805 intptr_t GetDataSize() { | 831 intptr_t GetDataSize() { |
| 806 return buffer_.GetDataSize(); | 832 return buffer_.GetDataSize(); |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 826 memset(&overlapped_, 0, sizeof(overlapped_)); | 852 memset(&overlapped_, 0, sizeof(overlapped_)); |
| 827 overlapped_.hEvent = event_; | 853 overlapped_.hEvent = event_; |
| 828 } | 854 } |
| 829 | 855 |
| 830 OVERLAPPED overlapped_; | 856 OVERLAPPED overlapped_; |
| 831 HANDLE handle_; | 857 HANDLE handle_; |
| 832 HANDLE event_; | 858 HANDLE event_; |
| 833 BufferList buffer_; | 859 BufferList buffer_; |
| 834 | 860 |
| 835 DISALLOW_ALLOCATION(); | 861 DISALLOW_ALLOCATION(); |
| 862 DISALLOW_COPY_AND_ASSIGN(OverlappedHandle); | |
| 836 }; | 863 }; |
| 837 | 864 |
| 838 | 865 |
| 839 bool Process::Wait(intptr_t pid, | 866 bool Process::Wait(intptr_t pid, |
| 840 intptr_t in, | 867 intptr_t in, |
| 841 intptr_t out, | 868 intptr_t out, |
| 842 intptr_t err, | 869 intptr_t err, |
| 843 intptr_t exit_event, | 870 intptr_t exit_event, |
| 844 ProcessResult* result) { | 871 ProcessResult* result) { |
| 845 // Close input to the process right away. | 872 // Close input to the process right away. |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 898 } | 925 } |
| 899 } | 926 } |
| 900 } | 927 } |
| 901 | 928 |
| 902 // All handles closed and all data read. | 929 // All handles closed and all data read. |
| 903 result->set_stdout_data(oh[0].GetData()); | 930 result->set_stdout_data(oh[0].GetData()); |
| 904 result->set_stderr_data(oh[1].GetData()); | 931 result->set_stderr_data(oh[1].GetData()); |
| 905 | 932 |
| 906 // Calculate the exit code. | 933 // Calculate the exit code. |
| 907 ASSERT(oh[2].GetDataSize() == 8); | 934 ASSERT(oh[2].GetDataSize() == 8); |
| 908 uint32_t exit[2]; | 935 uint32_t exit_codes[2]; |
| 909 memmove(&exit, oh[2].GetFirstDataBuffer(), sizeof(exit)); | 936 memmove(&exit_codes, oh[2].GetFirstDataBuffer(), sizeof(exit_codes)); |
| 910 oh[2].FreeDataBuffer(); | 937 oh[2].FreeDataBuffer(); |
| 911 intptr_t exit_code = exit[0]; | 938 intptr_t exit_code = exit_codes[0]; |
| 912 intptr_t negative = exit[1]; | 939 intptr_t negative = exit_codes[1]; |
| 913 if (negative) exit_code = -exit_code; | 940 if (negative) { |
| 941 exit_code = -exit_code; | |
| 942 } | |
| 914 result->set_exit_code(exit_code); | 943 result->set_exit_code(exit_code); |
| 915 return true; | 944 return true; |
| 916 } | 945 } |
| 917 | 946 |
| 918 | 947 |
| 919 bool Process::Kill(intptr_t id, int signal) { | 948 bool Process::Kill(intptr_t id, int signal) { |
| 920 USE(signal); // signal is not used on Windows. | 949 USE(signal); // signal is not used on Windows. |
| 921 HANDLE process_handle; | 950 HANDLE process_handle; |
| 922 HANDLE wait_handle; | 951 HANDLE wait_handle; |
| 923 HANDLE exit_pipe; | 952 HANDLE exit_pipe; |
| 924 // First check the process info list for the process to get a handle to it. | 953 // First check the process info list for the process to get a handle to it. |
| 925 bool success = ProcessInfoList::LookupProcess(id, | 954 bool success = ProcessInfoList::LookupProcess(id, |
| 926 &process_handle, | 955 &process_handle, |
| 927 &wait_handle, | 956 &wait_handle, |
| 928 &exit_pipe); | 957 &exit_pipe); |
| 929 // For detached processes we don't have the process registered in the | 958 // For detached processes we don't have the process registered in the |
| 930 // process info list. Try to look it up through the OS. | 959 // process info list. Try to look it up through the OS. |
| 931 if (!success) { | 960 if (!success) { |
| 932 process_handle = OpenProcess(PROCESS_TERMINATE, FALSE, id); | 961 process_handle = OpenProcess(PROCESS_TERMINATE, FALSE, id); |
| 933 // The process is already dead. | 962 // The process is already dead. |
| 934 if (process_handle == INVALID_HANDLE_VALUE) return false; | 963 if (process_handle == INVALID_HANDLE_VALUE) { |
| 964 return false; | |
| 965 } | |
| 935 } | 966 } |
| 936 BOOL result = TerminateProcess(process_handle, -1); | 967 BOOL result = TerminateProcess(process_handle, -1); |
| 937 return result ? true : false; | 968 return result ? true : false; |
| 938 } | 969 } |
| 939 | 970 |
| 940 | 971 |
| 941 void Process::TerminateExitCodeHandler() { | 972 void Process::TerminateExitCodeHandler() { |
| 942 // Nothing needs to be done on Windows. | 973 // Nothing needs to be done on Windows. |
| 943 } | 974 } |
| 944 | 975 |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 978 case kSighup: return CTRL_CLOSE_EVENT; | 1009 case kSighup: return CTRL_CLOSE_EVENT; |
| 979 case kSigint: return CTRL_C_EVENT; | 1010 case kSigint: return CTRL_C_EVENT; |
| 980 default: | 1011 default: |
| 981 return -1; | 1012 return -1; |
| 982 } | 1013 } |
| 983 } | 1014 } |
| 984 | 1015 |
| 985 | 1016 |
| 986 intptr_t Process::SetSignalHandler(intptr_t signal) { | 1017 intptr_t Process::SetSignalHandler(intptr_t signal) { |
| 987 signal = GetWinSignal(signal); | 1018 signal = GetWinSignal(signal); |
| 988 if (signal == -1) return -1; | 1019 if (signal == -1) { |
| 1020 return -1; | |
| 1021 } | |
| 989 | 1022 |
| 990 // Generate a unique pipe name for the named pipe. | 1023 // Generate a unique pipe name for the named pipe. |
| 991 wchar_t pipe_name[kMaxPipeNameSize]; | 1024 wchar_t pipe_name[kMaxPipeNameSize]; |
| 992 int status = GenerateNames<1>(&pipe_name); | 1025 int status = GenerateNames<1>(&pipe_name); |
| 993 if (status != 0) return status; | 1026 if (status != 0) { |
| 1027 return status; | |
| 1028 } | |
| 994 | 1029 |
| 995 HANDLE fds[2]; | 1030 HANDLE fds[2]; |
| 996 if (!CreateProcessPipe(fds, pipe_name, kInheritNone)) { | 1031 if (!CreateProcessPipe(fds, pipe_name, kInheritNone)) { |
| 997 int error_code = GetLastError(); | 1032 int error_code = GetLastError(); |
| 998 CloseProcessPipe(fds); | 1033 CloseProcessPipe(fds); |
| 999 SetLastError(error_code); | 1034 SetLastError(error_code); |
| 1000 return -1; | 1035 return -1; |
| 1001 } | 1036 } |
| 1002 MutexLocker lock(signal_mutex); | 1037 MutexLocker lock(signal_mutex); |
| 1003 FileHandle* write_handle = new FileHandle(fds[kWriteHandle]); | 1038 FileHandle* write_handle = new FileHandle(fds[kWriteHandle]); |
| 1004 write_handle->EnsureInitialized(EventHandler::delegate()); | 1039 write_handle->EnsureInitialized(EventHandler::delegate()); |
| 1005 intptr_t write_fd = reinterpret_cast<intptr_t>(write_handle); | 1040 intptr_t write_fd = reinterpret_cast<intptr_t>(write_handle); |
| 1006 if (signal_handlers == NULL) { | 1041 if (signal_handlers == NULL) { |
| 1007 if (SetConsoleCtrlHandler(SignalHandler, true) == 0) { | 1042 if (SetConsoleCtrlHandler(SignalHandler, true) == 0) { |
| 1008 int error_code = GetLastError(); | 1043 int error_code = GetLastError(); |
| 1009 delete write_handle; | 1044 delete write_handle; |
| 1010 CloseProcessPipe(fds); | 1045 CloseProcessPipe(fds); |
| 1011 SetLastError(error_code); | 1046 SetLastError(error_code); |
| 1012 return -1; | 1047 return -1; |
| 1013 } | 1048 } |
| 1014 } | 1049 } |
| 1015 signal_handlers = new SignalInfo(write_fd, signal, signal_handlers); | 1050 signal_handlers = new SignalInfo(write_fd, signal, signal_handlers); |
| 1016 return reinterpret_cast<intptr_t>(new FileHandle(fds[kReadHandle])); | 1051 return reinterpret_cast<intptr_t>(new FileHandle(fds[kReadHandle])); |
| 1017 } | 1052 } |
| 1018 | 1053 |
| 1019 | 1054 |
| 1020 void Process::ClearSignalHandler(intptr_t signal) { | 1055 void Process::ClearSignalHandler(intptr_t signal) { |
| 1021 signal = GetWinSignal(signal); | 1056 signal = GetWinSignal(signal); |
| 1022 if (signal == -1) return; | 1057 if (signal == -1) { |
| 1058 return; | |
| 1059 } | |
| 1023 MutexLocker lock(signal_mutex); | 1060 MutexLocker lock(signal_mutex); |
| 1024 SignalInfo* handler = signal_handlers; | 1061 SignalInfo* handler = signal_handlers; |
| 1025 while (handler != NULL) { | 1062 while (handler != NULL) { |
| 1026 if (handler->port() == Dart_GetMainPortId() && | 1063 if ((handler->port() == Dart_GetMainPortId()) && |
| 1027 handler->signal() == signal) { | 1064 (handler->signal() == signal)) { |
| 1028 handler->Unlink(); | 1065 handler->Unlink(); |
| 1029 break; | 1066 break; |
| 1030 } | 1067 } |
| 1031 handler = handler->next(); | 1068 handler = handler->next(); |
| 1032 } | 1069 } |
| 1033 if (handler != NULL) { | 1070 if (handler != NULL) { |
| 1034 if (signal_handlers == handler) { | 1071 if (signal_handlers == handler) { |
| 1035 signal_handlers = handler->next(); | 1072 signal_handlers = handler->next(); |
| 1036 } | 1073 } |
| 1037 if (signal_handlers == NULL) { | 1074 if (signal_handlers == NULL) { |
| 1038 USE(SetConsoleCtrlHandler(SignalHandler, false)); | 1075 USE(SetConsoleCtrlHandler(SignalHandler, false)); |
| 1039 } | 1076 } |
| 1040 } | 1077 } |
| 1041 delete handler; | 1078 delete handler; |
| 1042 } | 1079 } |
| 1043 | 1080 |
| 1044 } // namespace bin | 1081 } // namespace bin |
| 1045 } // namespace dart | 1082 } // namespace dart |
| 1046 | 1083 |
| 1047 #endif // defined(TARGET_OS_WINDOWS) | 1084 #endif // defined(TARGET_OS_WINDOWS) |
| OLD | NEW |