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

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

Issue 2791423002: [dart:io] Don't close stdin with a socket finalizer (Closed)
Patch Set: Windows 7 fix Created 3 years, 8 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
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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 #if !defined(DART_IO_DISABLED) 5 #if !defined(DART_IO_DISABLED)
6 6
7 #include "platform/globals.h" 7 #include "platform/globals.h"
8 #if defined(HOST_OS_WINDOWS) 8 #if defined(HOST_OS_WINDOWS)
9 9
10 #include "bin/eventhandler.h" 10 #include "bin/eventhandler.h"
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
149 return (completion_port_ != NULL); 149 return (completion_port_ != NULL);
150 } 150 }
151 151
152 152
153 void Handle::Close() { 153 void Handle::Close() {
154 MonitorLocker ml(monitor_); 154 MonitorLocker ml(monitor_);
155 if (!SupportsOverlappedIO()) { 155 if (!SupportsOverlappedIO()) {
156 // If the handle uses synchronous I/O (e.g. stdin), cancel any pending 156 // If the handle uses synchronous I/O (e.g. stdin), cancel any pending
157 // operation before closing the handle, so the read thread is not blocked. 157 // operation before closing the handle, so the read thread is not blocked.
158 BOOL result = CancelIoEx(handle_, NULL); 158 BOOL result = CancelIoEx(handle_, NULL);
159 ASSERT(result || (GetLastError() == ERROR_NOT_FOUND)); 159 // The Dart code 'stdin.listen(() {}).cancel()' causes this assert to be
160 // triggered on Windows 7, but not on Windows 10.
161 #if defined(DEBUG)
162 if (IsWindows10OrGreater()) {
163 ASSERT(result || (GetLastError() == ERROR_NOT_FOUND));
164 }
165 #else
166 USE(result);
167 #endif
160 } 168 }
161 if (!IsClosing()) { 169 if (!IsClosing()) {
162 // Close the socket and set the closing state. This close method can be 170 // Close the socket and set the closing state. This close method can be
163 // called again if this socket has pending IO operations in flight. 171 // called again if this socket has pending IO operations in flight.
164 MarkClosing(); 172 MarkClosing();
165 // Perform handle type specific closing. 173 // Perform handle type specific closing.
166 DoClose(); 174 DoClose();
167 } 175 }
168 ASSERT(IsHandleClosed()); 176 ASSERT(IsHandleClosed());
169 } 177 }
(...skipping 576 matching lines...) Expand 10 before | Expand all | Expand 10 after
746 } 754 }
747 pending_write_ = OverlappedBuffer::AllocateSendToBuffer(num_bytes); 755 pending_write_ = OverlappedBuffer::AllocateSendToBuffer(num_bytes);
748 pending_write_->Write(buffer, num_bytes); 756 pending_write_->Write(buffer, num_bytes);
749 if (!IssueSendTo(sa, sa_len)) { 757 if (!IssueSendTo(sa, sa_len)) {
750 return -1; 758 return -1;
751 } 759 }
752 return num_bytes; 760 return num_bytes;
753 } 761 }
754 762
755 763
764 Mutex* StdHandle::stdin_mutex_ = new Mutex();
765 StdHandle* StdHandle::stdin_ = NULL;
766
767 StdHandle* StdHandle::Stdin(HANDLE handle) {
768 MutexLocker ml(stdin_mutex_);
769 if (stdin_ == NULL) {
770 stdin_ = new StdHandle(handle);
771 }
772 return stdin_;
773 }
774
775
756 static void WriteFileThread(uword args) { 776 static void WriteFileThread(uword args) {
757 StdHandle* handle = reinterpret_cast<StdHandle*>(args); 777 StdHandle* handle = reinterpret_cast<StdHandle*>(args);
758 handle->RunWriteLoop(); 778 handle->RunWriteLoop();
759 } 779 }
760 780
761 781
762 void StdHandle::RunWriteLoop() { 782 void StdHandle::RunWriteLoop() {
763 MonitorLocker ml(monitor_); 783 MonitorLocker ml(monitor_);
764 write_thread_running_ = true; 784 write_thread_running_ = true;
765 thread_id_ = Thread::GetCurrentThreadId(); 785 thread_id_ = Thread::GetCurrentThreadId();
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
838 int truncated_bytes = Utils::Minimum<intptr_t>(num_bytes, INT_MAX); 858 int truncated_bytes = Utils::Minimum<intptr_t>(num_bytes, INT_MAX);
839 // Create buffer and notify thread about the new handle. 859 // Create buffer and notify thread about the new handle.
840 pending_write_ = OverlappedBuffer::AllocateWriteBuffer(truncated_bytes); 860 pending_write_ = OverlappedBuffer::AllocateWriteBuffer(truncated_bytes);
841 pending_write_->Write(buffer, truncated_bytes); 861 pending_write_->Write(buffer, truncated_bytes);
842 ml.Notify(); 862 ml.Notify();
843 return 0; 863 return 0;
844 } 864 }
845 865
846 866
847 void StdHandle::DoClose() { 867 void StdHandle::DoClose() {
848 MonitorLocker ml(monitor_); 868 {
849 if (write_thread_exists_) { 869 MonitorLocker ml(monitor_);
850 write_thread_running_ = false; 870 if (write_thread_exists_) {
851 ml.Notify(); 871 write_thread_running_ = false;
852 while (write_thread_exists_) { 872 ml.Notify();
853 ml.Wait(Monitor::kNoTimeout); 873 while (write_thread_exists_) {
874 ml.Wait(Monitor::kNoTimeout);
875 }
876 // Join the thread.
877 DWORD res = WaitForSingleObject(thread_handle_, INFINITE);
878 CloseHandle(thread_handle_);
879 ASSERT(res == WAIT_OBJECT_0);
854 } 880 }
855 // Join the thread. 881 Handle::DoClose();
856 DWORD res = WaitForSingleObject(thread_handle_, INFINITE);
857 CloseHandle(thread_handle_);
858 ASSERT(res == WAIT_OBJECT_0);
859 } 882 }
860 Handle::DoClose(); 883 MutexLocker ml(stdin_mutex_);
884 stdin_->Release();
885 StdHandle::stdin_ = NULL;
861 } 886 }
862 887
863 888
864 #if defined(DEBUG) 889 #if defined(DEBUG)
865 intptr_t ClientSocket::disconnecting_ = 0; 890 intptr_t ClientSocket::disconnecting_ = 0;
866 #endif 891 #endif
867 892
868 893
869 bool ClientSocket::LoadDisconnectEx() { 894 bool ClientSocket::LoadDisconnectEx() {
870 // Load the DisconnectEx function into memory using WSAIoctl. 895 // Load the DisconnectEx function into memory using WSAIoctl.
(...skipping 634 matching lines...) Expand 10 before | Expand all | Expand 10 after
1505 #if defined(DEBUG) 1530 #if defined(DEBUG)
1506 while (true) { 1531 while (true) {
1507 ok = GetQueuedCompletionStatus(handler_impl->completion_port(), &bytes, 1532 ok = GetQueuedCompletionStatus(handler_impl->completion_port(), &bytes,
1508 &key, &overlapped, 0); 1533 &key, &overlapped, 0);
1509 if (!ok && (overlapped == NULL)) { 1534 if (!ok && (overlapped == NULL)) {
1510 // There was an error or nothing is ready. Assume the port is drained. 1535 // There was an error or nothing is ready. Assume the port is drained.
1511 break; 1536 break;
1512 } 1537 }
1513 handler_impl->HandleCompletionOrInterrupt(ok, bytes, key, overlapped); 1538 handler_impl->HandleCompletionOrInterrupt(ok, bytes, key, overlapped);
1514 } 1539 }
1515 #endif
1516 1540
1517 // The eventhandler thread is going down so there should be no more live 1541 // The eventhandler thread is going down so there should be no more live
1518 // Handles or Sockets. 1542 // Handles or Sockets.
1519 // TODO(dart:io): It would be nice to be able to assert here that: 1543 // TODO(dart:io): It would be nice to be able to assert here that:
1520 // ReferenceCounted<Handle>::instances() == 0; 1544 // ReferenceCounted<Handle>::instances() == 0;
1521 // However, we cannot at the moment. See the TODO on: 1545 // However, we cannot at the moment. See the TODO on:
1522 // ClientSocket::IssueDisconnect() 1546 // ClientSocket::IssueDisconnect()
1547 // Furthermore, if the Dart program references stdin, but does not
1548 // explicitly close it, then the StdHandle for it will be leaked to here.
1549 const intptr_t stdin_leaked = (StdHandle::StdinPtr() == NULL) ? 0 : 1;
1523 DEBUG_ASSERT(ReferenceCounted<Handle>::instances() == 1550 DEBUG_ASSERT(ReferenceCounted<Handle>::instances() ==
1524 ClientSocket::disconnecting()); 1551 ClientSocket::disconnecting() + stdin_leaked);
1525 DEBUG_ASSERT(ReferenceCounted<Socket>::instances() == 0); 1552 DEBUG_ASSERT(ReferenceCounted<Socket>::instances() == 0);
1553 #endif // defined(DEBUG)
1526 handler->NotifyShutdownDone(); 1554 handler->NotifyShutdownDone();
1527 } 1555 }
1528 1556
1529 1557
1530 void EventHandlerImplementation::Start(EventHandler* handler) { 1558 void EventHandlerImplementation::Start(EventHandler* handler) {
1531 int result = 1559 int result =
1532 Thread::Start(EventHandlerEntry, reinterpret_cast<uword>(handler)); 1560 Thread::Start(EventHandlerEntry, reinterpret_cast<uword>(handler));
1533 if (result != 0) { 1561 if (result != 0) {
1534 FATAL1("Failed to start event handler thread %d", result); 1562 FATAL1("Failed to start event handler thread %d", result);
1535 } 1563 }
(...skipping 15 matching lines...) Expand all
1551 void EventHandlerImplementation::Shutdown() { 1579 void EventHandlerImplementation::Shutdown() {
1552 SendData(kShutdownId, 0, 0); 1580 SendData(kShutdownId, 0, 0);
1553 } 1581 }
1554 1582
1555 } // namespace bin 1583 } // namespace bin
1556 } // namespace dart 1584 } // namespace dart
1557 1585
1558 #endif // defined(HOST_OS_WINDOWS) 1586 #endif // defined(HOST_OS_WINDOWS)
1559 1587
1560 #endif // !defined(DART_IO_DISABLED) 1588 #endif // !defined(DART_IO_DISABLED)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698