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