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

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: Combined the code from https://codereview.chromium.org/22827002/ into this change 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 BufferList: public BufferListBase {
646 public:
647 BufferList() : read_pending_(true) { }
648
649 void DataRead(intptr_t size) {
Bill Hesse 2013/08/13 08:34:48 Maybe DataIsRead, to distinguish between the prese
Søren Gjesse 2013/08/13 13:00:43 Done. Added a comment as well.
650 ASSERT(read_pending_ == true);
651 data_size_ += size;
652 free_size_ -= size;
653 ASSERT(free_size_ >= 0);
654 read_pending_ = false;
655 }
656
657 void GetReadBuffer(uint8_t** buffer, intptr_t* size) {
658 ASSERT(!read_pending_);
659 if (free_size_ == 0) Allocate();
660 ASSERT(free_size_ > 0);
661 ASSERT(free_size_ <= kBufferSize);
662 *buffer = tail_->data_ + (kBufferSize - free_size_);
663 *size = free_size_;
664 read_pending_ = true;
665 }
666
667 intptr_t GetDataSize() {
668 return data_size_;
669 }
670
671 uint8_t* GetDataBuffer() {
672 return head_->data_;
Bill Hesse 2013/08/13 08:34:48 ASSERT(head_->next == NULL)?
Søren Gjesse 2013/08/13 13:00:43 Done.
673 }
674
675 void FreeDataBuffer() {
676 Free();
677 }
678
679 private:
680 bool read_pending_;
681 };
682
683
684 class OverlappedHandle {
685 public:
686 void Init(HANDLE handle, HANDLE event) {
687 handle_ = handle;
688 event_ = event;
689 ClearOverlapped();
690 }
691
692 bool HasEvent(HANDLE event) {
693 return event_ == event;
694 }
695
696 bool Read() {
697 // Get the data read as a rasult of a completed overlapped operation.
Bill Hesse 2013/08/13 08:34:48 result
Søren Gjesse 2013/08/13 13:00:43 Done.
698 if (overlapped_.InternalHigh > 0) {
699 buffer_.DataRead(overlapped_.InternalHigh);
700 } else {
701 buffer_.DataRead(0);
702 }
703
704 // Keep reading until error or pending operation.
705 while (true) {
706 ClearOverlapped();
707 uint8_t* buffer;
708 intptr_t buffer_size;
709 buffer_.GetReadBuffer(&buffer, &buffer_size);
710 BOOL ok = ReadFile(handle_, buffer, buffer_size, NULL, &overlapped_);
711 if (!ok) return GetLastError() == ERROR_IO_PENDING;
712 buffer_.DataRead(overlapped_.InternalHigh);
713 }
714 }
715
716 Dart_Handle GetData() {
717 return buffer_.GetData();
718 }
719
720 intptr_t GetDataSize() {
721 return buffer_.GetDataSize();
722 }
723
724 uint8_t* GetDataBuffer() {
725 return buffer_.GetDataBuffer();
726 }
727
728 void FreeDataBuffer() {
729 return buffer_.FreeDataBuffer();
730 }
731
732 void Close() {
733 CloseHandle(handle_);
734 CloseHandle(event_);
735 handle_ = INVALID_HANDLE_VALUE;
736 overlapped_.hEvent = INVALID_HANDLE_VALUE;
737 }
738
739 private:
740 void ClearOverlapped() {
741 memset(&overlapped_, 0, sizeof(overlapped_));
742 overlapped_.hEvent = event_;
743 }
744
745 OVERLAPPED overlapped_;
746 HANDLE handle_;
747 HANDLE event_;
748 BufferList buffer_;
749
750 DISALLOW_ALLOCATION();
751 };
752
753
754 bool Process::Wait(intptr_t pid,
755 intptr_t in,
756 intptr_t out,
757 intptr_t err,
758 intptr_t exit_event,
759 ProcessResult* result) {
760 // Close input to the process right away.
761 reinterpret_cast<FileHandle*>(in)->Close();
762
763 // All pipes created to the sub-process supports overlapped IO.
Bill Hesse 2013/08/13 08:34:48 support
Søren Gjesse 2013/08/13 13:00:43 Done.
764 FileHandle* stdout_handle = reinterpret_cast<FileHandle*>(out);
765 ASSERT(stdout_handle->SupportsOverlappedIO());
766 FileHandle* stderr_handle = reinterpret_cast<FileHandle*>(err);
767 ASSERT(stderr_handle->SupportsOverlappedIO());
768 FileHandle* exit_handle = reinterpret_cast<FileHandle*>(exit_event);
769 ASSERT(exit_handle->SupportsOverlappedIO());
770
771 // Create three events for overlapped IO. These are created as already
772 // signalled to ensure they have read called at least once.
773 static const int kHandles = 3;
774 HANDLE events[kHandles];
775 for (int i = 0; i < kHandles; i++) {
776 events[i] = CreateEvent(NULL, FALSE, TRUE, NULL);
777 }
778
779 // Setup the structure for handling overlapped IO.
780 OverlappedHandle oh[kHandles];
781 oh[0].Init(stdout_handle->handle(), events[0]);
782 oh[1].Init(stderr_handle->handle(), events[1]);
783 oh[2].Init(exit_handle->handle(), events[2]);
784
785 // Continue until all handles are closed.
786 int alive = kHandles;
787 while (alive > 0) {
788 // Blocking call waiting for events from the child process.
789 DWORD wait_result = WaitForMultipleObjects(alive, events, FALSE, INFINITE);
790
791 // Find the handle signalled.
792 int index = wait_result - WAIT_OBJECT_0;
793 for (int i = 0; i < kHandles; i++) {
794 if (oh[i].HasEvent(events[index])) {
795 bool ok = oh[i].Read();
796 if (!ok) {
797 if (GetLastError() == ERROR_BROKEN_PIPE) {
798 oh[i].Close();
799 alive--;
800 if (index < alive) {
801 events[index] = events[alive];
802 }
803 } else if (err != ERROR_IO_PENDING) {
804 DWORD e = GetLastError();
805 oh[0].Close();
806 oh[1].Close();
807 oh[2].Close();
808 SetLastError(e);
809 return false;
810 }
811 }
812 break;
813 }
814 }
815 }
816
817 // All handles closed and all data read.
818 result->set_stdout_data(oh[0].GetData());
819 result->set_stderr_data(oh[1].GetData());
820
821 // Calculate the exit code.
822 ASSERT(oh[2].GetDataSize() == 8);
823 uint32_t exit[2];
824 memcpy(&exit, oh[2].GetDataBuffer(), sizeof(exit));
Bill Hesse 2013/08/13 08:34:48 I would call this "GetFirstBufferSegment" or "GetF
Søren Gjesse 2013/08/13 13:00:43 Done.
825 oh[2].FreeDataBuffer();
826 intptr_t exit_code = exit[0];
827 intptr_t negative = exit[1];
828 if (negative) exit_code = -exit_code;
829 result->set_exit_code(exit_code);
830 return true;
831 }
832
833
645 bool Process::Kill(intptr_t id, int signal) { 834 bool Process::Kill(intptr_t id, int signal) {
646 USE(signal); // signal is not used on windows. 835 USE(signal); // signal is not used on windows.
647 HANDLE process_handle; 836 HANDLE process_handle;
648 HANDLE wait_handle; 837 HANDLE wait_handle;
649 HANDLE exit_pipe; 838 HANDLE exit_pipe;
650 bool success = ProcessInfoList::LookupProcess(id, 839 bool success = ProcessInfoList::LookupProcess(id,
651 &process_handle, 840 &process_handle,
652 &wait_handle, 841 &wait_handle,
653 &exit_pipe); 842 &exit_pipe);
654 // The process is already dead. 843 // The process is already dead.
655 if (!success) return false; 844 if (!success) return false;
656 BOOL result = TerminateProcess(process_handle, -1); 845 BOOL result = TerminateProcess(process_handle, -1);
657 return result ? true : false; 846 return result ? true : false;
658 } 847 }
659 848
660 849
661 void Process::TerminateExitCodeHandler() { 850 void Process::TerminateExitCodeHandler() {
662 // Nothing needs to be done on Windows. 851 // Nothing needs to be done on Windows.
663 } 852 }
664 853
665 854
666 intptr_t Process::CurrentProcessId() { 855 intptr_t Process::CurrentProcessId() {
667 return static_cast<intptr_t>(GetCurrentProcessId()); 856 return static_cast<intptr_t>(GetCurrentProcessId());
668 } 857 }
669 858
670 } // namespace bin 859 } // namespace bin
671 } // namespace dart 860 } // namespace dart
672 861
673 #endif // defined(TARGET_OS_WINDOWS) 862 #endif // defined(TARGET_OS_WINDOWS)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698