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 <process.h> // NOLINT | 8 #include <process.h> // NOLINT |
9 | 9 |
10 #include "bin/builtin.h" | 10 #include "bin/builtin.h" |
(...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
299 HANDLE handles4[2]) { | 299 HANDLE handles4[2]) { |
300 CloseProcessPipe(handles1); | 300 CloseProcessPipe(handles1); |
301 CloseProcessPipe(handles2); | 301 CloseProcessPipe(handles2); |
302 CloseProcessPipe(handles3); | 302 CloseProcessPipe(handles3); |
303 CloseProcessPipe(handles4); | 303 CloseProcessPipe(handles4); |
304 } | 304 } |
305 | 305 |
306 | 306 |
307 static int SetOsErrorMessage(char** os_error_message) { | 307 static int SetOsErrorMessage(char** os_error_message) { |
308 int error_code = GetLastError(); | 308 int error_code = GetLastError(); |
309 static const int kMaxMessageLength = 256; | 309 const int kMaxMessageLength = 256; |
310 wchar_t message[kMaxMessageLength]; | 310 wchar_t message[kMaxMessageLength]; |
311 FormatMessageIntoBuffer(error_code, message, kMaxMessageLength); | 311 FormatMessageIntoBuffer(error_code, message, kMaxMessageLength); |
312 *os_error_message = StringUtils::WideToUtf8(message); | 312 *os_error_message = StringUtils::WideToUtf8(message); |
313 return error_code; | 313 return error_code; |
314 } | 314 } |
315 | 315 |
316 | 316 |
| 317 // Open an inheritable handle to NUL. |
| 318 static HANDLE OpenNul() { |
| 319 SECURITY_ATTRIBUTES inherit_handle; |
| 320 inherit_handle.nLength = sizeof(SECURITY_ATTRIBUTES); |
| 321 inherit_handle.bInheritHandle = TRUE; |
| 322 inherit_handle.lpSecurityDescriptor = NULL; |
| 323 HANDLE nul = CreateFile(L"NUL", |
| 324 GENERIC_READ | GENERIC_WRITE, |
| 325 0, |
| 326 &inherit_handle, |
| 327 OPEN_EXISTING, |
| 328 0, |
| 329 NULL); |
| 330 if (nul == INVALID_HANDLE_VALUE) { |
| 331 Log::PrintErr("CloseHandle failed %d\n", GetLastError()); |
| 332 } |
| 333 return nul; |
| 334 } |
| 335 |
| 336 |
317 typedef BOOL (WINAPI *InitProcThreadAttrListFn)( | 337 typedef BOOL (WINAPI *InitProcThreadAttrListFn)( |
318 LPPROC_THREAD_ATTRIBUTE_LIST, DWORD, DWORD, PSIZE_T); | 338 LPPROC_THREAD_ATTRIBUTE_LIST, DWORD, DWORD, PSIZE_T); |
319 | 339 |
320 typedef BOOL (WINAPI *UpdateProcThreadAttrFn)( | 340 typedef BOOL (WINAPI *UpdateProcThreadAttrFn)( |
321 LPPROC_THREAD_ATTRIBUTE_LIST, DWORD, DWORD_PTR, | 341 LPPROC_THREAD_ATTRIBUTE_LIST, DWORD, DWORD_PTR, |
322 PVOID, SIZE_T, PVOID, PSIZE_T); | 342 PVOID, SIZE_T, PVOID, PSIZE_T); |
323 | 343 |
324 typedef VOID (WINAPI *DeleteProcThreadAttrListFn)( | 344 typedef VOID (WINAPI *DeleteProcThreadAttrListFn)( |
325 LPPROC_THREAD_ATTRIBUTE_LIST); | 345 LPPROC_THREAD_ATTRIBUTE_LIST); |
326 | 346 |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
378 return 0; | 398 return 0; |
379 } | 399 } |
380 | 400 |
381 | 401 |
382 int Process::Start(const char* path, | 402 int Process::Start(const char* path, |
383 char* arguments[], | 403 char* arguments[], |
384 intptr_t arguments_length, | 404 intptr_t arguments_length, |
385 const char* working_directory, | 405 const char* working_directory, |
386 char* environment[], | 406 char* environment[], |
387 intptr_t environment_length, | 407 intptr_t environment_length, |
| 408 bool detach, |
388 intptr_t* in, | 409 intptr_t* in, |
389 intptr_t* out, | 410 intptr_t* out, |
390 intptr_t* err, | 411 intptr_t* err, |
391 intptr_t* id, | 412 intptr_t* id, |
392 intptr_t* exit_handler, | 413 intptr_t* exit_handler, |
393 char** os_error_message) { | 414 char** os_error_message) { |
394 HANDLE stdin_handles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE }; | 415 HANDLE stdin_handles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE }; |
395 HANDLE stdout_handles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE }; | 416 HANDLE stdout_handles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE }; |
396 HANDLE stderr_handles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE }; | 417 HANDLE stderr_handles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE }; |
397 HANDLE exit_handles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE }; | 418 HANDLE exit_handles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE }; |
398 | 419 |
399 // Generate unique pipe names for the four named pipes needed. | 420 // Generate unique pipe names for the four named pipes needed. |
400 wchar_t pipe_names[4][kMaxPipeNameSize]; | 421 wchar_t pipe_names[4][kMaxPipeNameSize]; |
401 int status = GenerateNames<4>(pipe_names); | 422 int status = GenerateNames<4>(pipe_names); |
402 if (status != 0) { | 423 if (status != 0) { |
403 SetOsErrorMessage(os_error_message); | 424 SetOsErrorMessage(os_error_message); |
404 Log::PrintErr("UuidCreateSequential failed %d\n", status); | 425 Log::PrintErr("UuidCreateSequential failed %d\n", status); |
405 return status; | 426 return status; |
406 } | 427 } |
407 | 428 |
408 if (!CreateProcessPipe(stdin_handles, pipe_names[0], kInheritRead)) { | 429 if (!detach) { |
409 int error_code = SetOsErrorMessage(os_error_message); | 430 // Open pipes for stdin, stdout, stderr and for communicating the exit |
410 CloseProcessPipes( | 431 // code. |
411 stdin_handles, stdout_handles, stderr_handles, exit_handles); | 432 if (!CreateProcessPipe(stdin_handles, pipe_names[0], kInheritRead)) { |
412 return error_code; | 433 int error_code = SetOsErrorMessage(os_error_message); |
413 } | 434 CloseProcessPipes( |
414 if (!CreateProcessPipe(stdout_handles, pipe_names[1], kInheritWrite)) { | 435 stdin_handles, stdout_handles, stderr_handles, exit_handles); |
415 int error_code = SetOsErrorMessage(os_error_message); | 436 return error_code; |
416 CloseProcessPipes( | 437 } |
417 stdin_handles, stdout_handles, stderr_handles, exit_handles); | 438 if (!CreateProcessPipe(stdout_handles, pipe_names[1], kInheritWrite)) { |
418 return error_code; | 439 int error_code = SetOsErrorMessage(os_error_message); |
419 } | 440 CloseProcessPipes( |
420 if (!CreateProcessPipe(stderr_handles, pipe_names[2], kInheritWrite)) { | 441 stdin_handles, stdout_handles, stderr_handles, exit_handles); |
421 int error_code = SetOsErrorMessage(os_error_message); | 442 return error_code; |
422 CloseProcessPipes( | 443 } |
423 stdin_handles, stdout_handles, stderr_handles, exit_handles); | 444 if (!CreateProcessPipe(stderr_handles, pipe_names[2], kInheritWrite)) { |
424 return error_code; | 445 int error_code = SetOsErrorMessage(os_error_message); |
425 } | 446 CloseProcessPipes( |
426 if (!CreateProcessPipe(exit_handles, pipe_names[3], kInheritNone)) { | 447 stdin_handles, stdout_handles, stderr_handles, exit_handles); |
427 int error_code = SetOsErrorMessage(os_error_message); | 448 return error_code; |
428 CloseProcessPipes( | 449 } |
429 stdin_handles, stdout_handles, stderr_handles, exit_handles); | 450 if (!CreateProcessPipe(exit_handles, pipe_names[3], kInheritNone)) { |
430 return error_code; | 451 int error_code = SetOsErrorMessage(os_error_message); |
| 452 CloseProcessPipes( |
| 453 stdin_handles, stdout_handles, stderr_handles, exit_handles); |
| 454 return error_code; |
| 455 } |
| 456 } else { |
| 457 // Open NUL for stdin, stdout and stderr. |
| 458 stdin_handles[kReadHandle] = OpenNul(); |
| 459 if (stdin_handles[kReadHandle] == INVALID_HANDLE_VALUE) { |
| 460 int error_code = SetOsErrorMessage(os_error_message); |
| 461 CloseProcessPipes( |
| 462 stdin_handles, stdout_handles, stderr_handles, exit_handles); |
| 463 return error_code; |
| 464 } |
| 465 stdout_handles[kWriteHandle] = OpenNul(); |
| 466 if (stdout_handles[kWriteHandle] == INVALID_HANDLE_VALUE) { |
| 467 int error_code = SetOsErrorMessage(os_error_message); |
| 468 CloseProcessPipes( |
| 469 stdin_handles, stdout_handles, stderr_handles, exit_handles); |
| 470 return error_code; |
| 471 } |
| 472 stderr_handles[kWriteHandle] = OpenNul(); |
| 473 if (stderr_handles[kWriteHandle] == INVALID_HANDLE_VALUE) { |
| 474 int error_code = SetOsErrorMessage(os_error_message); |
| 475 CloseProcessPipes( |
| 476 stdin_handles, stdout_handles, stderr_handles, exit_handles); |
| 477 return error_code; |
| 478 } |
431 } | 479 } |
432 | 480 |
433 // Setup info structures. | 481 // Setup info structures. |
434 STARTUPINFOEXW startup_info; | 482 STARTUPINFOEXW startup_info; |
435 ZeroMemory(&startup_info, sizeof(startup_info)); | 483 ZeroMemory(&startup_info, sizeof(startup_info)); |
436 startup_info.StartupInfo.cb = sizeof(startup_info); | 484 startup_info.StartupInfo.cb = sizeof(startup_info); |
437 startup_info.StartupInfo.hStdInput = stdin_handles[kReadHandle]; | 485 startup_info.StartupInfo.hStdInput = stdin_handles[kReadHandle]; |
438 startup_info.StartupInfo.hStdOutput = stdout_handles[kWriteHandle]; | 486 startup_info.StartupInfo.hStdOutput = stdout_handles[kWriteHandle]; |
439 startup_info.StartupInfo.hStdError = stderr_handles[kWriteHandle]; | 487 startup_info.StartupInfo.hStdError = stderr_handles[kWriteHandle]; |
440 startup_info.StartupInfo.dwFlags = STARTF_USESTDHANDLES; | 488 startup_info.StartupInfo.dwFlags = STARTF_USESTDHANDLES; |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
575 } | 623 } |
576 | 624 |
577 const wchar_t* system_working_directory = NULL; | 625 const wchar_t* system_working_directory = NULL; |
578 if (working_directory != NULL) { | 626 if (working_directory != NULL) { |
579 system_working_directory = StringUtils::Utf8ToWide(working_directory); | 627 system_working_directory = StringUtils::Utf8ToWide(working_directory); |
580 } | 628 } |
581 | 629 |
582 // Create process. | 630 // Create process. |
583 DWORD creation_flags = | 631 DWORD creation_flags = |
584 EXTENDED_STARTUPINFO_PRESENT | CREATE_UNICODE_ENVIRONMENT; | 632 EXTENDED_STARTUPINFO_PRESENT | CREATE_UNICODE_ENVIRONMENT; |
| 633 if (detach) { |
| 634 creation_flags |= DETACHED_PROCESS; |
| 635 } |
585 BOOL result = CreateProcessW(NULL, // ApplicationName | 636 BOOL result = CreateProcessW(NULL, // ApplicationName |
586 command_line, | 637 command_line, |
587 NULL, // ProcessAttributes | 638 NULL, // ProcessAttributes |
588 NULL, // ThreadAttributes | 639 NULL, // ThreadAttributes |
589 TRUE, // InheritHandles | 640 TRUE, // InheritHandles |
590 creation_flags, | 641 creation_flags, |
591 environment_block, | 642 environment_block, |
592 system_working_directory, | 643 system_working_directory, |
593 reinterpret_cast<STARTUPINFOW*>(&startup_info), | 644 reinterpret_cast<STARTUPINFOW*>(&startup_info), |
594 &process_info); | 645 &process_info); |
595 | |
596 // Deallocate command-line and environment block strings. | 646 // Deallocate command-line and environment block strings. |
597 delete[] command_line; | 647 delete[] command_line; |
598 delete[] environment_block; | 648 delete[] environment_block; |
599 if (system_working_directory != NULL) { | 649 if (system_working_directory != NULL) { |
600 free(const_cast<wchar_t*>(system_working_directory)); | 650 free(const_cast<wchar_t*>(system_working_directory)); |
601 } | 651 } |
602 | 652 |
603 if (supports_proc_thread_attr_lists) { | 653 if (supports_proc_thread_attr_lists) { |
604 delete_proc_thread_attr_list(attribute_list); | 654 delete_proc_thread_attr_list(attribute_list); |
605 free(attribute_list); | 655 free(attribute_list); |
606 } | 656 } |
607 | 657 |
608 if (result == 0) { | 658 if (result == 0) { |
609 int error_code = SetOsErrorMessage(os_error_message); | 659 int error_code = SetOsErrorMessage(os_error_message); |
610 CloseProcessPipes( | 660 CloseProcessPipes( |
611 stdin_handles, stdout_handles, stderr_handles, exit_handles); | 661 stdin_handles, stdout_handles, stderr_handles, exit_handles); |
612 return error_code; | 662 return error_code; |
613 } | 663 } |
614 | 664 |
615 ProcessInfoList::AddProcess(process_info.dwProcessId, | 665 CloseHandle(stdin_handles[kReadHandle]); |
616 process_info.hProcess, | 666 CloseHandle(stdout_handles[kWriteHandle]); |
617 exit_handles[kWriteHandle]); | 667 CloseHandle(stderr_handles[kWriteHandle]); |
| 668 if (!detach) { |
| 669 ProcessInfoList::AddProcess(process_info.dwProcessId, |
| 670 process_info.hProcess, |
| 671 exit_handles[kWriteHandle]); |
618 | 672 |
619 // Connect the three std streams. | 673 // Connect the three std streams. |
620 FileHandle* stdin_handle = new FileHandle(stdin_handles[kWriteHandle]); | 674 FileHandle* stdin_handle = new FileHandle(stdin_handles[kWriteHandle]); |
621 CloseHandle(stdin_handles[kReadHandle]); | 675 FileHandle* stdout_handle = new FileHandle(stdout_handles[kReadHandle]); |
622 FileHandle* stdout_handle = new FileHandle(stdout_handles[kReadHandle]); | 676 FileHandle* stderr_handle = new FileHandle(stderr_handles[kReadHandle]); |
623 CloseHandle(stdout_handles[kWriteHandle]); | 677 FileHandle* exit_handle = new FileHandle(exit_handles[kReadHandle]); |
624 FileHandle* stderr_handle = new FileHandle(stderr_handles[kReadHandle]); | 678 *in = reinterpret_cast<intptr_t>(stdout_handle); |
625 CloseHandle(stderr_handles[kWriteHandle]); | 679 *out = reinterpret_cast<intptr_t>(stdin_handle); |
626 FileHandle* exit_handle = new FileHandle(exit_handles[kReadHandle]); | 680 *err = reinterpret_cast<intptr_t>(stderr_handle); |
627 *in = reinterpret_cast<intptr_t>(stdout_handle); | 681 *exit_handler = reinterpret_cast<intptr_t>(exit_handle); |
628 *out = reinterpret_cast<intptr_t>(stdin_handle); | 682 } |
629 *err = reinterpret_cast<intptr_t>(stderr_handle); | |
630 *exit_handler = reinterpret_cast<intptr_t>(exit_handle); | |
631 | 683 |
632 CloseHandle(process_info.hThread); | 684 CloseHandle(process_info.hThread); |
633 | 685 |
634 // Return process id. | 686 // Return process id. |
635 *id = process_info.dwProcessId; | 687 *id = process_info.dwProcessId; |
636 return 0; | 688 return 0; |
637 } | 689 } |
638 | 690 |
639 | 691 |
640 class BufferList: public BufferListBase { | 692 class BufferList: public BufferListBase { |
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
826 oh[2].FreeDataBuffer(); | 878 oh[2].FreeDataBuffer(); |
827 intptr_t exit_code = exit[0]; | 879 intptr_t exit_code = exit[0]; |
828 intptr_t negative = exit[1]; | 880 intptr_t negative = exit[1]; |
829 if (negative) exit_code = -exit_code; | 881 if (negative) exit_code = -exit_code; |
830 result->set_exit_code(exit_code); | 882 result->set_exit_code(exit_code); |
831 return true; | 883 return true; |
832 } | 884 } |
833 | 885 |
834 | 886 |
835 bool Process::Kill(intptr_t id, int signal) { | 887 bool Process::Kill(intptr_t id, int signal) { |
836 USE(signal); // signal is not used on windows. | 888 USE(signal); // signal is not used on Windows. |
837 HANDLE process_handle; | 889 HANDLE process_handle; |
838 HANDLE wait_handle; | 890 HANDLE wait_handle; |
839 HANDLE exit_pipe; | 891 HANDLE exit_pipe; |
| 892 // First check the process info list for the process to get a handle to it. |
840 bool success = ProcessInfoList::LookupProcess(id, | 893 bool success = ProcessInfoList::LookupProcess(id, |
841 &process_handle, | 894 &process_handle, |
842 &wait_handle, | 895 &wait_handle, |
843 &exit_pipe); | 896 &exit_pipe); |
844 // The process is already dead. | 897 // For detached processes we don't have the process registered in the |
845 if (!success) return false; | 898 // process info list. Try to look it up through the OS. |
| 899 if (!success) { |
| 900 process_handle = OpenProcess(PROCESS_TERMINATE, FALSE, id); |
| 901 // The process is already dead. |
| 902 if (process_handle == INVALID_HANDLE_VALUE) return false; |
| 903 } |
846 BOOL result = TerminateProcess(process_handle, -1); | 904 BOOL result = TerminateProcess(process_handle, -1); |
847 return result ? true : false; | 905 return result ? true : false; |
848 } | 906 } |
849 | 907 |
850 | 908 |
851 void Process::TerminateExitCodeHandler() { | 909 void Process::TerminateExitCodeHandler() { |
852 // Nothing needs to be done on Windows. | 910 // Nothing needs to be done on Windows. |
853 } | 911 } |
854 | 912 |
855 | 913 |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
948 USE(SetConsoleCtrlHandler(SignalHandler, false)); | 1006 USE(SetConsoleCtrlHandler(SignalHandler, false)); |
949 } | 1007 } |
950 } | 1008 } |
951 delete handler; | 1009 delete handler; |
952 } | 1010 } |
953 | 1011 |
954 } // namespace bin | 1012 } // namespace bin |
955 } // namespace dart | 1013 } // namespace dart |
956 | 1014 |
957 #endif // defined(TARGET_OS_WINDOWS) | 1015 #endif // defined(TARGET_OS_WINDOWS) |
OLD | NEW |