| 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) { |
| 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_; |
| 673 } |
| 674 |
| 675 void FreeDataBuffer() { |
| 676 Free(); |
| 677 } |
| 678 |
| 679 private: |
| 680 bool read_pending_; |
| 681 }; |
| 682 |
| 683 |
| 645 class OverlappedHandle { | 684 class OverlappedHandle { |
| 646 public: | 685 public: |
| 647 static const int kBufferSize = 16 * 1024; | |
| 648 | |
| 649 void Init(HANDLE handle, HANDLE event) { | 686 void Init(HANDLE handle, HANDLE event) { |
| 650 handle_ = handle; | 687 handle_ = handle; |
| 651 event_ = event; | 688 event_ = event; |
| 652 ClearOverlapped(); | 689 ClearOverlapped(); |
| 653 data_ = NULL; | |
| 654 data_length_ = 0; | |
| 655 } | 690 } |
| 656 | 691 |
| 657 bool HasEvent(HANDLE event) { | 692 bool HasEvent(HANDLE event) { |
| 658 return event_ == event; | 693 return event_ == event; |
| 659 } | 694 } |
| 660 | 695 |
| 661 bool Read() { | 696 bool Read() { |
| 662 // Get the data read as a rasult of a completed overlapped operation. | 697 // Get the data read as a rasult of a completed overlapped operation. |
| 663 if (overlapped_.InternalHigh > 0) { | 698 if (overlapped_.InternalHigh > 0) { |
| 664 AddData(overlapped_.InternalHigh); | 699 buffer_.DataRead(overlapped_.InternalHigh); |
| 700 } else { |
| 701 buffer_.DataRead(0); |
| 665 } | 702 } |
| 666 | 703 |
| 667 // Keep reading until error or pending operation. | 704 // Keep reading until error or pending operation. |
| 668 while (true) { | 705 while (true) { |
| 669 ClearOverlapped(); | 706 ClearOverlapped(); |
| 670 BOOL ok = ReadFile(handle_, buffer_, kBufferSize, NULL, &overlapped_); | 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_); |
| 671 if (!ok) return GetLastError() == ERROR_IO_PENDING; | 711 if (!ok) return GetLastError() == ERROR_IO_PENDING; |
| 672 AddData(overlapped_.InternalHigh); | 712 buffer_.DataRead(overlapped_.InternalHigh); |
| 673 } | 713 } |
| 674 } | 714 } |
| 675 | 715 |
| 676 uint8_t* data() { return data_; } | 716 Dart_Handle GetData() { |
| 677 intptr_t data_length() { return data_length_; } | 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 } |
| 678 | 731 |
| 679 void Close() { | 732 void Close() { |
| 680 CloseHandle(handle_); | 733 CloseHandle(handle_); |
| 681 CloseHandle(event_); | 734 CloseHandle(event_); |
| 682 handle_ = INVALID_HANDLE_VALUE; | 735 handle_ = INVALID_HANDLE_VALUE; |
| 683 overlapped_.hEvent = INVALID_HANDLE_VALUE; | 736 overlapped_.hEvent = INVALID_HANDLE_VALUE; |
| 684 } | 737 } |
| 685 | 738 |
| 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: | 739 private: |
| 698 void ClearOverlapped() { | 740 void ClearOverlapped() { |
| 699 memset(&overlapped_, 0, sizeof(overlapped_)); | 741 memset(&overlapped_, 0, sizeof(overlapped_)); |
| 700 overlapped_.hEvent = event_; | 742 overlapped_.hEvent = event_; |
| 701 } | 743 } |
| 702 | 744 |
| 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_; | 745 OVERLAPPED overlapped_; |
| 714 HANDLE handle_; | 746 HANDLE handle_; |
| 715 HANDLE event_; | 747 HANDLE event_; |
| 716 char buffer_[kBufferSize]; | 748 BufferList buffer_; |
| 717 uint8_t* data_; | |
| 718 intptr_t data_length_; | |
| 719 | 749 |
| 720 DISALLOW_ALLOCATION(); | 750 DISALLOW_ALLOCATION(); |
| 721 }; | 751 }; |
| 722 | 752 |
| 723 | 753 |
| 724 bool Process::Wait(intptr_t pid, | 754 bool Process::Wait(intptr_t pid, |
| 725 intptr_t in, | 755 intptr_t in, |
| 726 intptr_t out, | 756 intptr_t out, |
| 727 intptr_t err, | 757 intptr_t err, |
| 728 intptr_t exit_event, | 758 intptr_t exit_event, |
| (...skipping 12 matching lines...) Expand all Loading... |
| 741 // Create three events for overlapped IO. These are created as already | 771 // Create three events for overlapped IO. These are created as already |
| 742 // signalled to ensure they have read called at least once. | 772 // signalled to ensure they have read called at least once. |
| 743 static const int kHandles = 3; | 773 static const int kHandles = 3; |
| 744 HANDLE events[kHandles]; | 774 HANDLE events[kHandles]; |
| 745 for (int i = 0; i < kHandles; i++) { | 775 for (int i = 0; i < kHandles; i++) { |
| 746 events[i] = CreateEvent(NULL, FALSE, TRUE, NULL); | 776 events[i] = CreateEvent(NULL, FALSE, TRUE, NULL); |
| 747 } | 777 } |
| 748 | 778 |
| 749 // Setup the structure for handling overlapped IO. | 779 // Setup the structure for handling overlapped IO. |
| 750 OverlappedHandle oh[kHandles]; | 780 OverlappedHandle oh[kHandles]; |
| 751 memset(&oh, 0, sizeof(oh)); | |
| 752 oh[0].Init(stdout_handle->handle(), events[0]); | 781 oh[0].Init(stdout_handle->handle(), events[0]); |
| 753 oh[1].Init(stderr_handle->handle(), events[1]); | 782 oh[1].Init(stderr_handle->handle(), events[1]); |
| 754 oh[2].Init(exit_handle->handle(), events[2]); | 783 oh[2].Init(exit_handle->handle(), events[2]); |
| 755 | 784 |
| 756 // Continue until all handles are closed. | 785 // Continue until all handles are closed. |
| 757 int alive = kHandles; | 786 int alive = kHandles; |
| 758 while (alive > 0) { | 787 while (alive > 0) { |
| 759 // Blocking call waiting for events from the child process. | 788 // Blocking call waiting for events from the child process. |
| 760 DWORD wait_result = WaitForMultipleObjects(alive, events, FALSE, INFINITE); | 789 DWORD wait_result = WaitForMultipleObjects(alive, events, FALSE, INFINITE); |
| 761 | 790 |
| 762 // Find the handle signalled. | 791 // Find the handle signalled. |
| 763 int index = wait_result - WAIT_OBJECT_0; | 792 int index = wait_result - WAIT_OBJECT_0; |
| 764 for (int i = 0; i < kHandles; i++) { | 793 for (int i = 0; i < kHandles; i++) { |
| 765 if (oh[i].HasEvent(events[index])) { | 794 if (oh[i].HasEvent(events[index])) { |
| 766 bool ok = oh[i].Read(); | 795 bool ok = oh[i].Read(); |
| 767 if (!ok) { | 796 if (!ok) { |
| 768 if (GetLastError() == ERROR_BROKEN_PIPE) { | 797 if (GetLastError() == ERROR_BROKEN_PIPE) { |
| 769 oh[i].Close(); | 798 oh[i].Close(); |
| 770 alive--; | 799 alive--; |
| 771 if (index < alive) { | 800 if (index < alive) { |
| 772 events[index] = events[alive]; | 801 events[index] = events[alive]; |
| 773 } | 802 } |
| 774 } else if (err != ERROR_IO_PENDING) { | 803 } else if (err != ERROR_IO_PENDING) { |
| 775 DWORD e = GetLastError(); | 804 DWORD e = GetLastError(); |
| 776 oh[0].Destroy(); | 805 oh[0].Close(); |
| 777 oh[1].Destroy(); | 806 oh[1].Close(); |
| 778 oh[2].Destroy(); | 807 oh[2].Close(); |
| 779 SetLastError(e); | 808 SetLastError(e); |
| 780 return false; | 809 return false; |
| 781 } | 810 } |
| 782 } | 811 } |
| 783 break; | 812 break; |
| 784 } | 813 } |
| 785 } | 814 } |
| 786 } | 815 } |
| 787 | 816 |
| 788 // All handles closed and all data read. | 817 // All handles closed and all data read. |
| 789 result->SetStdoutData(oh[0].data(), oh[0].data_length()); | 818 result->set_stdout_data(oh[0].GetData()); |
| 790 result->SetStderrData(oh[1].data(), oh[1].data_length()); | 819 result->set_stderr_data(oh[1].GetData()); |
| 791 | 820 |
| 792 // Calculate the exit code. | 821 // Calculate the exit code. |
| 793 ASSERT(oh[2].data_length() == 8); | 822 ASSERT(oh[2].GetDataSize() == 8); |
| 794 uint32_t exit[2]; | 823 uint32_t exit[2]; |
| 795 memcpy(&exit, oh[2].data(), sizeof(exit)); | 824 memcpy(&exit, oh[2].GetDataBuffer(), sizeof(exit)); |
| 796 oh[2].FreeData(); | 825 oh[2].FreeDataBuffer(); |
| 797 intptr_t exit_code = exit[0]; | 826 intptr_t exit_code = exit[0]; |
| 798 intptr_t negative = exit[1]; | 827 intptr_t negative = exit[1]; |
| 799 if (negative) exit_code = -exit_code; | 828 if (negative) exit_code = -exit_code; |
| 800 result->set_exit_code(exit_code); | 829 result->set_exit_code(exit_code); |
| 801 return true; | 830 return true; |
| 802 } | 831 } |
| 803 | 832 |
| 804 | 833 |
| 805 bool Process::Kill(intptr_t id, int signal) { | 834 bool Process::Kill(intptr_t id, int signal) { |
| 806 USE(signal); // signal is not used on windows. | 835 USE(signal); // signal is not used on windows. |
| (...skipping 17 matching lines...) Expand all Loading... |
| 824 | 853 |
| 825 | 854 |
| 826 intptr_t Process::CurrentProcessId() { | 855 intptr_t Process::CurrentProcessId() { |
| 827 return static_cast<intptr_t>(GetCurrentProcessId()); | 856 return static_cast<intptr_t>(GetCurrentProcessId()); |
| 828 } | 857 } |
| 829 | 858 |
| 830 } // namespace bin | 859 } // namespace bin |
| 831 } // namespace dart | 860 } // namespace dart |
| 832 | 861 |
| 833 #endif // defined(TARGET_OS_WINDOWS) | 862 #endif // defined(TARGET_OS_WINDOWS) |
| OLD | NEW |