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

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

Issue 890633002: Add an option for starting a detached process with stdio connected (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Rebased Created 5 years, 10 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/io/process.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 381 matching lines...) Expand 10 before | Expand all | Expand 10 after
392 L"%s_%s_%d", prefix, uuid_string, i + 1); 392 L"%s_%s_%d", prefix, uuid_string, i + 1);
393 } 393 }
394 status = RpcStringFreeW(&uuid_string); 394 status = RpcStringFreeW(&uuid_string);
395 if (status != RPC_S_OK) { 395 if (status != RPC_S_OK) {
396 return status; 396 return status;
397 } 397 }
398 return 0; 398 return 0;
399 } 399 }
400 400
401 401
402 class ProcessStarter {
403 public:
404 ProcessStarter(const char* path,
405 char* arguments[],
406 intptr_t arguments_length,
407 const char* working_directory,
408 char* environment[],
409 intptr_t environment_length,
410 ProcessStartMode mode,
411 intptr_t* in,
412 intptr_t* out,
413 intptr_t* err,
414 intptr_t* id,
415 intptr_t* exit_handler,
416 char** os_error_message)
417 : path_(path),
418 working_directory_(working_directory),
419 mode_(mode),
420 in_(in),
421 out_(out),
422 err_(err),
423 id_(id),
424 exit_handler_(exit_handler),
425 os_error_message_(os_error_message) {
426 stdin_handles_[kReadHandle] = INVALID_HANDLE_VALUE;
427 stdin_handles_[kWriteHandle] = INVALID_HANDLE_VALUE;
428 stdout_handles_[kReadHandle] = INVALID_HANDLE_VALUE;
429 stdout_handles_[kWriteHandle] = INVALID_HANDLE_VALUE;
430 stderr_handles_[kReadHandle] = INVALID_HANDLE_VALUE;
431 stderr_handles_[kWriteHandle] = INVALID_HANDLE_VALUE;
432 exit_handles_[kReadHandle] = INVALID_HANDLE_VALUE;
433 exit_handles_[kWriteHandle] = INVALID_HANDLE_VALUE;
434
435 // Transform input strings to system format.
436 const wchar_t* system_path = StringUtils::Utf8ToWide(path_);
437 wchar_t** system_arguments = new wchar_t*[arguments_length];
438 for (int i = 0; i < arguments_length; i++) {
439 system_arguments[i] = StringUtils::Utf8ToWide(arguments[i]);
440 }
441
442 // Compute command-line length.
443 int command_line_length = wcslen(system_path);
444 for (int i = 0; i < arguments_length; i++) {
445 command_line_length += wcslen(system_arguments[i]);
446 }
447 // Account for null termination and one space per argument.
448 command_line_length += arguments_length + 1;
449
450 // Put together command-line string.
451 command_line_ = new wchar_t[command_line_length];
452 int len = 0;
453 int remaining = command_line_length;
454 int written =
455 _snwprintf(command_line_ + len, remaining, L"%s", system_path);
456 len += written;
457 remaining -= written;
458 ASSERT(remaining >= 0);
459 for (int i = 0; i < arguments_length; i++) {
460 written =
461 _snwprintf(
462 command_line_ + len, remaining, L" %s", system_arguments[i]);
463 len += written;
464 remaining -= written;
465 ASSERT(remaining >= 0);
466 }
467 free(const_cast<wchar_t*>(system_path));
468 for (int i = 0; i < arguments_length; i++) free(system_arguments[i]);
469 delete[] system_arguments;
470
471 // Create environment block if an environment is supplied.
472 environment_block_ = NULL;
473 if (environment != NULL) {
474 wchar_t** system_environment = new wchar_t*[environment_length];
475 // Convert environment strings to system strings.
476 for (intptr_t i = 0; i < environment_length; i++) {
477 system_environment[i] = StringUtils::Utf8ToWide(environment[i]);
478 }
479
480 // An environment block is a sequence of zero-terminated strings
481 // followed by a block-terminating zero char.
482 intptr_t block_size = 1;
483 for (intptr_t i = 0; i < environment_length; i++) {
484 block_size += wcslen(system_environment[i]) + 1;
485 }
486 environment_block_ = new wchar_t[block_size];
487 intptr_t block_index = 0;
488 for (intptr_t i = 0; i < environment_length; i++) {
489 intptr_t len = wcslen(system_environment[i]);
490 intptr_t result = _snwprintf(environment_block_ + block_index,
491 len,
492 L"%s",
493 system_environment[i]);
494 ASSERT(result == len);
495 block_index += len;
496 environment_block_[block_index++] = '\0';
497 }
498 // Block-terminating zero char.
499 environment_block_[block_index++] = '\0';
500 ASSERT(block_index == block_size);
501 for (intptr_t i = 0; i < environment_length; i++) {
502 free(system_environment[i]);
503 }
504 delete[] system_environment;
505 }
506
507 system_working_directory_ = NULL;
508 if (working_directory_ != NULL) {
509 system_working_directory_ = StringUtils::Utf8ToWide(working_directory_);
510 }
511
512 attribute_list_ = NULL;
513 }
514
515
516 ~ProcessStarter() {
517 // Deallocate command-line and environment block strings.
518 delete[] command_line_;
519 delete[] environment_block_;
520 if (system_working_directory_ != NULL) {
521 free(const_cast<wchar_t*>(system_working_directory_));
522 }
523 if (attribute_list_ != NULL) {
524 delete_proc_thread_attr_list(attribute_list_);
525 free(attribute_list_);
526 }
527 }
528
529
530 int Start() {
531 // Create pipes required.
532 int err = CreatePipes();
533 if (err != 0) return err;
534
535 // Setup info structures.
536 STARTUPINFOEXW startup_info;
537 ZeroMemory(&startup_info, sizeof(startup_info));
538 startup_info.StartupInfo.cb = sizeof(startup_info);
539 startup_info.StartupInfo.hStdInput = stdin_handles_[kReadHandle];
540 startup_info.StartupInfo.hStdOutput = stdout_handles_[kWriteHandle];
541 startup_info.StartupInfo.hStdError = stderr_handles_[kWriteHandle];
542 startup_info.StartupInfo.dwFlags = STARTF_USESTDHANDLES;
543
544 bool supports_proc_thread_attr_lists = EnsureInitialized();
545 if (supports_proc_thread_attr_lists) {
546 // Setup the handles to inherit. We only want to inherit the three handles
547 // for stdin, stdout and stderr.
548 SIZE_T size = 0;
549 // The call to determine the size of an attribute list always fails with
550 // ERROR_INSUFFICIENT_BUFFER and that error should be ignored.
551 if (!init_proc_thread_attr_list(NULL, 1, 0, &size) &&
552 GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
553 return CleanupAndReturnError();
554 }
555 attribute_list_ =
556 reinterpret_cast<LPPROC_THREAD_ATTRIBUTE_LIST>(malloc(size));
557 ZeroMemory(attribute_list_, size);
558 if (!init_proc_thread_attr_list(attribute_list_, 1, 0, &size)) {
559 return CleanupAndReturnError();
560 }
561 static const int kNumInheritedHandles = 3;
562 HANDLE inherited_handles[kNumInheritedHandles] =
563 { stdin_handles_[kReadHandle],
564 stdout_handles_[kWriteHandle],
565 stderr_handles_[kWriteHandle] };
566 if (!update_proc_thread_attr(attribute_list_,
567 0,
568 PROC_THREAD_ATTRIBUTE_HANDLE_LIST,
569 inherited_handles,
570 kNumInheritedHandles * sizeof(HANDLE),
571 NULL,
572 NULL)) {
573 return CleanupAndReturnError();
574 }
575 startup_info.lpAttributeList = attribute_list_;
576 }
577
578 PROCESS_INFORMATION process_info;
579 ZeroMemory(&process_info, sizeof(process_info));
580
581 // Create process.
582 DWORD creation_flags =
583 EXTENDED_STARTUPINFO_PRESENT | CREATE_UNICODE_ENVIRONMENT;
584 if (mode_ != kNormal) {
585 creation_flags |= DETACHED_PROCESS;
586 }
587 BOOL result = CreateProcessW(NULL, // ApplicationName
588 command_line_,
589 NULL, // ProcessAttributes
590 NULL, // ThreadAttributes
591 TRUE, // InheritHandles
592 creation_flags,
593 environment_block_,
594 system_working_directory_,
595 reinterpret_cast<STARTUPINFOW*>(&startup_info),
596 &process_info);
597
598 if (result == 0) {
599 return CleanupAndReturnError();
600 }
601
602 CloseHandle(stdin_handles_[kReadHandle]);
603 CloseHandle(stdout_handles_[kWriteHandle]);
604 CloseHandle(stderr_handles_[kWriteHandle]);
605 if (mode_ == kNormal) {
606 ProcessInfoList::AddProcess(process_info.dwProcessId,
607 process_info.hProcess,
608 exit_handles_[kWriteHandle]);
609 }
610 if (mode_ != kDetached) {
611 // Connect the three stdio streams.
612 FileHandle* stdin_handle = new FileHandle(stdin_handles_[kWriteHandle]);
613 FileHandle* stdout_handle = new FileHandle(stdout_handles_[kReadHandle]);
614 FileHandle* stderr_handle = new FileHandle(stderr_handles_[kReadHandle]);
615 *in_ = reinterpret_cast<intptr_t>(stdout_handle);
616 *out_ = reinterpret_cast<intptr_t>(stdin_handle);
617 *err_ = reinterpret_cast<intptr_t>(stderr_handle);
618 if (mode_ == kNormal) {
619 FileHandle* exit_handle = new FileHandle(exit_handles_[kReadHandle]);
620 *exit_handler_ = reinterpret_cast<intptr_t>(exit_handle);
621 }
622 }
623
624 CloseHandle(process_info.hThread);
625
626 // Return process id.
627 *id_ = process_info.dwProcessId;
628 return 0;
629 }
630
631
632 int CreatePipes() {
633 // Generate unique pipe names for the four named pipes needed.
634 wchar_t pipe_names[4][kMaxPipeNameSize];
635 int status = GenerateNames<4>(pipe_names);
636 if (status != 0) {
637 SetOsErrorMessage(os_error_message_);
638 Log::PrintErr("UuidCreateSequential failed %d\n", status);
639 return status;
640 }
641
642 if (mode_ != kDetached) {
643 // Open pipes for stdin, stdout, stderr and for communicating the exit
644 // code.
645 if (!CreateProcessPipe(stdin_handles_, pipe_names[0], kInheritRead) ||
646 !CreateProcessPipe(stdout_handles_, pipe_names[1], kInheritWrite) ||
647 !CreateProcessPipe(stderr_handles_, pipe_names[2], kInheritWrite)) {
648 return CleanupAndReturnError();
649 }
650 // Only open exit code pipe for non detached processes.
651 if (mode_ == kNormal) {
652 if (!CreateProcessPipe(exit_handles_, pipe_names[3], kInheritNone)) {
653 return CleanupAndReturnError();
654 }
655 }
656 } else {
657 // Open NUL for stdin, stdout and stderr.
658 if ((stdin_handles_[kReadHandle] = OpenNul()) == INVALID_HANDLE_VALUE ||
659 (stdout_handles_[kWriteHandle] = OpenNul()) == INVALID_HANDLE_VALUE ||
660 (stderr_handles_[kWriteHandle] = OpenNul()) == INVALID_HANDLE_VALUE) {
661 return CleanupAndReturnError();
662 }
663 }
664 return 0;
665 }
666
667
668 int CleanupAndReturnError() {
669 int error_code = SetOsErrorMessage(os_error_message_);
670 CloseProcessPipes(
671 stdin_handles_, stdout_handles_, stderr_handles_, exit_handles_);
672 return error_code;
673 }
674
675
676 HANDLE stdin_handles_[2];
677 HANDLE stdout_handles_[2];
678 HANDLE stderr_handles_[2];
679 HANDLE exit_handles_[2];
680
681 const wchar_t* system_working_directory_;
682 wchar_t* command_line_;
683 wchar_t* environment_block_;
684 LPPROC_THREAD_ATTRIBUTE_LIST attribute_list_;
685
686 const char* path_;
687 const char* working_directory_;
688 ProcessStartMode mode_;
689 intptr_t* in_;
690 intptr_t* out_;
691 intptr_t* err_;
692 intptr_t* id_;
693 intptr_t* exit_handler_;
694 char** os_error_message_;
695 };
696
697
402 int Process::Start(const char* path, 698 int Process::Start(const char* path,
403 char* arguments[], 699 char* arguments[],
404 intptr_t arguments_length, 700 intptr_t arguments_length,
405 const char* working_directory, 701 const char* working_directory,
406 char* environment[], 702 char* environment[],
407 intptr_t environment_length, 703 intptr_t environment_length,
408 bool detach, 704 ProcessStartMode mode,
409 intptr_t* in, 705 intptr_t* in,
410 intptr_t* out, 706 intptr_t* out,
411 intptr_t* err, 707 intptr_t* err,
412 intptr_t* id, 708 intptr_t* id,
413 intptr_t* exit_handler, 709 intptr_t* exit_handler,
414 char** os_error_message) { 710 char** os_error_message) {
415 HANDLE stdin_handles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE }; 711 ProcessStarter starter(path,
416 HANDLE stdout_handles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE }; 712 arguments,
417 HANDLE stderr_handles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE }; 713 arguments_length,
418 HANDLE exit_handles[2] = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE }; 714 working_directory,
419 715 environment,
420 // Generate unique pipe names for the four named pipes needed. 716 environment_length,
421 wchar_t pipe_names[4][kMaxPipeNameSize]; 717 mode,
422 int status = GenerateNames<4>(pipe_names); 718 in,
423 if (status != 0) { 719 out,
424 SetOsErrorMessage(os_error_message); 720 err,
425 Log::PrintErr("UuidCreateSequential failed %d\n", status); 721 id,
426 return status; 722 exit_handler,
427 } 723 os_error_message);
428 724 return starter.Start();
429 if (!detach) {
430 // Open pipes for stdin, stdout, stderr and for communicating the exit
431 // code.
432 if (!CreateProcessPipe(stdin_handles, pipe_names[0], kInheritRead)) {
433 int error_code = SetOsErrorMessage(os_error_message);
434 CloseProcessPipes(
435 stdin_handles, stdout_handles, stderr_handles, exit_handles);
436 return error_code;
437 }
438 if (!CreateProcessPipe(stdout_handles, pipe_names[1], kInheritWrite)) {
439 int error_code = SetOsErrorMessage(os_error_message);
440 CloseProcessPipes(
441 stdin_handles, stdout_handles, stderr_handles, exit_handles);
442 return error_code;
443 }
444 if (!CreateProcessPipe(stderr_handles, pipe_names[2], kInheritWrite)) {
445 int error_code = SetOsErrorMessage(os_error_message);
446 CloseProcessPipes(
447 stdin_handles, stdout_handles, stderr_handles, exit_handles);
448 return error_code;
449 }
450 if (!CreateProcessPipe(exit_handles, pipe_names[3], kInheritNone)) {
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 }
479 }
480
481 // Setup info structures.
482 STARTUPINFOEXW startup_info;
483 ZeroMemory(&startup_info, sizeof(startup_info));
484 startup_info.StartupInfo.cb = sizeof(startup_info);
485 startup_info.StartupInfo.hStdInput = stdin_handles[kReadHandle];
486 startup_info.StartupInfo.hStdOutput = stdout_handles[kWriteHandle];
487 startup_info.StartupInfo.hStdError = stderr_handles[kWriteHandle];
488 startup_info.StartupInfo.dwFlags = STARTF_USESTDHANDLES;
489
490 LPPROC_THREAD_ATTRIBUTE_LIST attribute_list = NULL;
491
492 bool supports_proc_thread_attr_lists = EnsureInitialized();
493 if (supports_proc_thread_attr_lists) {
494 // Setup the handles to inherit. We only want to inherit the three handles
495 // for stdin, stdout and stderr.
496 SIZE_T size = 0;
497 // The call to determine the size of an attribute list always fails with
498 // ERROR_INSUFFICIENT_BUFFER and that error should be ignored.
499 if (!init_proc_thread_attr_list(NULL, 1, 0, &size) &&
500 GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
501 int error_code = SetOsErrorMessage(os_error_message);
502 CloseProcessPipes(
503 stdin_handles, stdout_handles, stderr_handles, exit_handles);
504 return error_code;
505 }
506 attribute_list =
507 reinterpret_cast<LPPROC_THREAD_ATTRIBUTE_LIST>(malloc(size));
508 ZeroMemory(attribute_list, size);
509 if (!init_proc_thread_attr_list(attribute_list, 1, 0, &size)) {
510 int error_code = SetOsErrorMessage(os_error_message);
511 CloseProcessPipes(
512 stdin_handles, stdout_handles, stderr_handles, exit_handles);
513 free(attribute_list);
514 return error_code;
515 }
516 static const int kNumInheritedHandles = 3;
517 HANDLE inherited_handles[kNumInheritedHandles] =
518 { stdin_handles[kReadHandle],
519 stdout_handles[kWriteHandle],
520 stderr_handles[kWriteHandle] };
521 if (!update_proc_thread_attr(attribute_list,
522 0,
523 PROC_THREAD_ATTRIBUTE_HANDLE_LIST,
524 inherited_handles,
525 kNumInheritedHandles * sizeof(HANDLE),
526 NULL,
527 NULL)) {
528 delete_proc_thread_attr_list(attribute_list);
529 int error_code = SetOsErrorMessage(os_error_message);
530 CloseProcessPipes(
531 stdin_handles, stdout_handles, stderr_handles, exit_handles);
532 free(attribute_list);
533 return error_code;
534 }
535 startup_info.lpAttributeList = attribute_list;
536 }
537
538 PROCESS_INFORMATION process_info;
539 ZeroMemory(&process_info, sizeof(process_info));
540
541 // Transform input strings to system format.
542 const wchar_t* system_path = StringUtils::Utf8ToWide(path);
543 wchar_t** system_arguments = new wchar_t*[arguments_length];
544 for (int i = 0; i < arguments_length; i++) {
545 system_arguments[i] = StringUtils::Utf8ToWide(arguments[i]);
546 }
547
548 // Compute command-line length.
549 int command_line_length = wcslen(system_path);
550 for (int i = 0; i < arguments_length; i++) {
551 command_line_length += wcslen(system_arguments[i]);
552 }
553 // Account for null termination and one space per argument.
554 command_line_length += arguments_length + 1;
555 static const int kMaxCommandLineLength = 32768;
556 if (command_line_length > kMaxCommandLineLength) {
557 int error_code = SetOsErrorMessage(os_error_message);
558 CloseProcessPipes(
559 stdin_handles, stdout_handles, stderr_handles, exit_handles);
560 free(const_cast<wchar_t*>(system_path));
561 for (int i = 0; i < arguments_length; i++) free(system_arguments[i]);
562 delete[] system_arguments;
563 if (supports_proc_thread_attr_lists) {
564 delete_proc_thread_attr_list(attribute_list);
565 free(attribute_list);
566 }
567 return error_code;
568 }
569
570 // Put together command-line string.
571 wchar_t* command_line = new wchar_t[command_line_length];
572 int len = 0;
573 int remaining = command_line_length;
574 int written = _snwprintf(command_line + len, remaining, L"%s", system_path);
575 len += written;
576 remaining -= written;
577 ASSERT(remaining >= 0);
578 for (int i = 0; i < arguments_length; i++) {
579 written =
580 _snwprintf(command_line + len, remaining, L" %s", system_arguments[i]);
581 len += written;
582 remaining -= written;
583 ASSERT(remaining >= 0);
584 }
585 free(const_cast<wchar_t*>(system_path));
586 for (int i = 0; i < arguments_length; i++) free(system_arguments[i]);
587 delete[] system_arguments;
588
589 // Create environment block if an environment is supplied.
590 wchar_t* environment_block = NULL;
591 if (environment != NULL) {
592 wchar_t** system_environment = new wchar_t*[environment_length];
593 // Convert environment strings to system strings.
594 for (intptr_t i = 0; i < environment_length; i++) {
595 system_environment[i] = StringUtils::Utf8ToWide(environment[i]);
596 }
597
598 // An environment block is a sequence of zero-terminated strings
599 // followed by a block-terminating zero char.
600 intptr_t block_size = 1;
601 for (intptr_t i = 0; i < environment_length; i++) {
602 block_size += wcslen(system_environment[i]) + 1;
603 }
604 environment_block = new wchar_t[block_size];
605 intptr_t block_index = 0;
606 for (intptr_t i = 0; i < environment_length; i++) {
607 intptr_t len = wcslen(system_environment[i]);
608 intptr_t result = _snwprintf(environment_block + block_index,
609 len,
610 L"%s",
611 system_environment[i]);
612 ASSERT(result == len);
613 block_index += len;
614 environment_block[block_index++] = '\0';
615 }
616 // Block-terminating zero char.
617 environment_block[block_index++] = '\0';
618 ASSERT(block_index == block_size);
619 for (intptr_t i = 0; i < environment_length; i++) {
620 free(system_environment[i]);
621 }
622 delete[] system_environment;
623 }
624
625 const wchar_t* system_working_directory = NULL;
626 if (working_directory != NULL) {
627 system_working_directory = StringUtils::Utf8ToWide(working_directory);
628 }
629
630 // Create process.
631 DWORD creation_flags =
632 EXTENDED_STARTUPINFO_PRESENT | CREATE_UNICODE_ENVIRONMENT;
633 if (detach) {
634 creation_flags |= DETACHED_PROCESS;
635 }
636 BOOL result = CreateProcessW(NULL, // ApplicationName
637 command_line,
638 NULL, // ProcessAttributes
639 NULL, // ThreadAttributes
640 TRUE, // InheritHandles
641 creation_flags,
642 environment_block,
643 system_working_directory,
644 reinterpret_cast<STARTUPINFOW*>(&startup_info),
645 &process_info);
646 // Deallocate command-line and environment block strings.
647 delete[] command_line;
648 delete[] environment_block;
649 if (system_working_directory != NULL) {
650 free(const_cast<wchar_t*>(system_working_directory));
651 }
652
653 if (supports_proc_thread_attr_lists) {
654 delete_proc_thread_attr_list(attribute_list);
655 free(attribute_list);
656 }
657
658 if (result == 0) {
659 int error_code = SetOsErrorMessage(os_error_message);
660 CloseProcessPipes(
661 stdin_handles, stdout_handles, stderr_handles, exit_handles);
662 return error_code;
663 }
664
665 CloseHandle(stdin_handles[kReadHandle]);
666 CloseHandle(stdout_handles[kWriteHandle]);
667 CloseHandle(stderr_handles[kWriteHandle]);
668 if (!detach) {
669 ProcessInfoList::AddProcess(process_info.dwProcessId,
670 process_info.hProcess,
671 exit_handles[kWriteHandle]);
672
673 // Connect the three std streams.
674 FileHandle* stdin_handle = new FileHandle(stdin_handles[kWriteHandle]);
675 FileHandle* stdout_handle = new FileHandle(stdout_handles[kReadHandle]);
676 FileHandle* stderr_handle = new FileHandle(stderr_handles[kReadHandle]);
677 FileHandle* exit_handle = new FileHandle(exit_handles[kReadHandle]);
678 *in = reinterpret_cast<intptr_t>(stdout_handle);
679 *out = reinterpret_cast<intptr_t>(stdin_handle);
680 *err = reinterpret_cast<intptr_t>(stderr_handle);
681 *exit_handler = reinterpret_cast<intptr_t>(exit_handle);
682 }
683
684 CloseHandle(process_info.hThread);
685
686 // Return process id.
687 *id = process_info.dwProcessId;
688 return 0;
689 } 725 }
690 726
691 727
692 class BufferList: public BufferListBase { 728 class BufferList: public BufferListBase {
693 public: 729 public:
694 BufferList() : read_pending_(true) { } 730 BufferList() : read_pending_(true) { }
695 731
696 // Indicate that data has been read into the buffer provided to 732 // Indicate that data has been read into the buffer provided to
697 // overlapped read. 733 // overlapped read.
698 void DataIsRead(intptr_t size) { 734 void DataIsRead(intptr_t size) {
(...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after
1006 USE(SetConsoleCtrlHandler(SignalHandler, false)); 1042 USE(SetConsoleCtrlHandler(SignalHandler, false));
1007 } 1043 }
1008 } 1044 }
1009 delete handler; 1045 delete handler;
1010 } 1046 }
1011 1047
1012 } // namespace bin 1048 } // namespace bin
1013 } // namespace dart 1049 } // namespace dart
1014 1050
1015 #endif // defined(TARGET_OS_WINDOWS) 1051 #endif // defined(TARGET_OS_WINDOWS)
OLDNEW
« no previous file with comments | « runtime/bin/process_patch.dart ('k') | sdk/lib/io/process.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698