| 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 |