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

Side by Side Diff: runtime/bin/process_win.cc

Issue 798743004: Add support for starting a detached process (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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/bin/process_patch.dart ('k') | sdk/lib/_internal/compiler/js_lib/io_patch.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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)
OLDNEW
« no previous file with comments | « runtime/bin/process_patch.dart ('k') | sdk/lib/_internal/compiler/js_lib/io_patch.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698