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

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

Powered by Google App Engine
This is Rietveld 408576698