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

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

Issue 22827002: Change the allocation of the stdout and stderr collected by Process.runSync (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Minor fixes 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
« no previous file with comments | « runtime/bin/process_macos.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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) {
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
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
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)
OLDNEW
« no previous file with comments | « runtime/bin/process_macos.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698