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

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

Issue 21816002: Add Process.runSync for running processe synchronously. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Fixed Mac OS issue Created 7 years, 4 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
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 624 matching lines...) Expand 10 before | Expand all | Expand 10 after
635 *exit_handler = reinterpret_cast<intptr_t>(exit_handle); 635 *exit_handler = reinterpret_cast<intptr_t>(exit_handle);
636 636
637 CloseHandle(process_info.hThread); 637 CloseHandle(process_info.hThread);
638 638
639 // Return process id. 639 // Return process id.
640 *id = process_info.dwProcessId; 640 *id = process_info.dwProcessId;
641 return 0; 641 return 0;
642 } 642 }
643 643
644 644
645 class OverlappedHandle {
646 public:
647 static const int kBufferSize = 16 * 1024;
648
649 void Init(HANDLE handle, HANDLE event) {
650 handle_ = handle;
651 event_ = event;
652 ClearOverlapped();
653 data_ = NULL;
654 data_length_ = 0;
655 }
656
657 bool HasEvent(HANDLE event) {
658 return event_ == event;
659 }
660
661 bool Read() {
662 // Get the data read as a rasult of a completed overlapped operation.
663 if (overlapped_.InternalHigh > 0) {
664 AddData(overlapped_.InternalHigh);
665 }
666
667 // Keep reading until error or pending operation.
668 while (true) {
669 ClearOverlapped();
670 BOOL ok = ReadFile(handle_, buffer_, kBufferSize, NULL, &overlapped_);
671 if (!ok) return GetLastError() == ERROR_IO_PENDING;
672 AddData(overlapped_.InternalHigh);
673 }
674 }
675
676 uint8_t* data() { return data_; }
677 intptr_t data_length() { return data_length_; }
678
679 void Close() {
680 CloseHandle(handle_);
681 CloseHandle(event_);
682 handle_ = INVALID_HANDLE_VALUE;
683 overlapped_.hEvent = INVALID_HANDLE_VALUE;
684 }
685
686 void FreeData() {
687 free(data_);
688 data_ = NULL;
689 data_length_ = 0;
690 }
691
692 void Destroy() {
693 Close();
694 FreeData();
695 }
696
697 private:
698 void ClearOverlapped() {
699 memset(&overlapped_, 0, sizeof(overlapped_));
700 overlapped_.hEvent = event_;
701 }
702
703 void AddData(DWORD length) {
704 uint8_t* tmp = new uint8_t[data_length_ + length];
705 if (tmp == NULL) FATAL("Allocation failed");
706 memmove(tmp, data_, data_length_);
707 memmove(tmp + data_length_, buffer_, length);
708 delete[] data_;
709 data_ = tmp;
710 data_length_ += length;
711 }
712
713 OVERLAPPED overlapped_;
714 HANDLE handle_;
715 HANDLE event_;
716 char buffer_[kBufferSize];
717 uint8_t* data_;
718 intptr_t data_length_;
719
720 DISALLOW_ALLOCATION();
721 };
722
723
724 bool Process::Wait(intptr_t pid,
725 intptr_t in,
726 intptr_t out,
727 intptr_t err,
728 intptr_t exit_event,
729 ProcessResult* result) {
730 // Close input to the process right away.
731 reinterpret_cast<FileHandle*>(in)->Close();
732
733 // All pipes created to the sub-process supports overlapped IO.
734 FileHandle* stdout_handle = reinterpret_cast<FileHandle*>(out);
735 ASSERT(stdout_handle->SupportsOverlappedIO());
736 FileHandle* stderr_handle = reinterpret_cast<FileHandle*>(err);
737 ASSERT(stderr_handle->SupportsOverlappedIO());
738 FileHandle* exit_handle = reinterpret_cast<FileHandle*>(exit_event);
739 ASSERT(exit_handle->SupportsOverlappedIO());
740
741 // Create three events for overlapped IO. These are created as already
742 // signalled to ensure they have read called at least once.
743 static const int kHandles = 3;
744 HANDLE events[kHandles];
745 for (int i = 0; i < kHandles; i++) {
746 events[i] = CreateEvent(NULL, FALSE, TRUE, NULL);
747 }
748
749 // Setup the structure for handling overlapped IO.
750 OverlappedHandle oh[kHandles];
751 memset(&oh, 0, sizeof(oh));
752 oh[0].Init(stdout_handle->handle(), events[0]);
753 oh[1].Init(stderr_handle->handle(), events[1]);
754 oh[2].Init(exit_handle->handle(), events[2]);
755
756 // Continue until all handles are closed.
757 int alive = kHandles;
758 while (alive > 0) {
759 // Wait for event to become signalled.
760 DWORD wait_result = WaitForMultipleObjects(alive, events, FALSE, INFINITE);
761
762 // Find the handle signalled.
763 int index = wait_result - WAIT_OBJECT_0;
764 for (int i = 0; i < kHandles; i++) {
765 if (oh[i].HasEvent(events[index])) {
766 bool ok = oh[i].Read();
767 if (!ok) {
768 if (GetLastError() == ERROR_BROKEN_PIPE) {
769 oh[i].Close();
770 alive--;
771 if (index < alive) {
772 events[index] = events[alive];
773 }
774 } else if (err != ERROR_IO_PENDING) {
775 DWORD e = GetLastError();
776 oh[0].Destroy();
777 oh[1].Destroy();
778 oh[2].Destroy();
779 SetLastError(e);
780 return false;
781 }
782 }
783 break;
784 }
785 }
786 }
787
788 // All handles closed and all data read.
789 result->SetStdoutData(oh[0].data(), oh[0].data_length());
790 result->SetStderrData(oh[1].data(), oh[1].data_length());
791
792 // Calculate the exit code.
793 ASSERT(oh[2].data_length() == 8);
794 uint32_t exit[2];
795 memcpy(&exit, oh[2].data(), sizeof(exit));
796 oh[2].FreeData();
797 intptr_t exit_code = exit[0];
798 intptr_t negative = exit[1];
799 if (negative) exit_code = -exit_code;
800 result->set_exit_code(exit_code);
801 return true;
802 }
803
804
645 bool Process::Kill(intptr_t id, int signal) { 805 bool Process::Kill(intptr_t id, int signal) {
646 USE(signal); // signal is not used on windows. 806 USE(signal); // signal is not used on windows.
647 HANDLE process_handle; 807 HANDLE process_handle;
648 HANDLE wait_handle; 808 HANDLE wait_handle;
649 HANDLE exit_pipe; 809 HANDLE exit_pipe;
650 bool success = ProcessInfoList::LookupProcess(id, 810 bool success = ProcessInfoList::LookupProcess(id,
651 &process_handle, 811 &process_handle,
652 &wait_handle, 812 &wait_handle,
653 &exit_pipe); 813 &exit_pipe);
654 // The process is already dead. 814 // The process is already dead.
655 if (!success) return false; 815 if (!success) return false;
656 BOOL result = TerminateProcess(process_handle, -1); 816 BOOL result = TerminateProcess(process_handle, -1);
657 return result ? true : false; 817 return result ? true : false;
658 } 818 }
659 819
660 820
661 void Process::TerminateExitCodeHandler() { 821 void Process::TerminateExitCodeHandler() {
662 // Nothing needs to be done on Windows. 822 // Nothing needs to be done on Windows.
663 } 823 }
664 824
665 825
666 intptr_t Process::CurrentProcessId() { 826 intptr_t Process::CurrentProcessId() {
667 return static_cast<intptr_t>(GetCurrentProcessId()); 827 return static_cast<intptr_t>(GetCurrentProcessId());
668 } 828 }
669 829
670 } // namespace bin 830 } // namespace bin
671 } // namespace dart 831 } // namespace dart
672 832
673 #endif // defined(TARGET_OS_WINDOWS) 833 #endif // defined(TARGET_OS_WINDOWS)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698