Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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) |
| OLD | NEW |