| Index: runtime/bin/eventhandler_win.cc
|
| diff --git a/runtime/bin/eventhandler_win.cc b/runtime/bin/eventhandler_win.cc
|
| index e961581be4827226a2fc72e8be21be5d325150ac..a6c16a6480f44e781d4f5de0fa485313ec5389f9 100644
|
| --- a/runtime/bin/eventhandler_win.cc
|
| +++ b/runtime/bin/eventhandler_win.cc
|
| @@ -156,7 +156,15 @@ void Handle::Close() {
|
| // If the handle uses synchronous I/O (e.g. stdin), cancel any pending
|
| // operation before closing the handle, so the read thread is not blocked.
|
| BOOL result = CancelIoEx(handle_, NULL);
|
| - ASSERT(result || (GetLastError() == ERROR_NOT_FOUND));
|
| +// The Dart code 'stdin.listen(() {}).cancel()' causes this assert to be
|
| +// triggered on Windows 7, but not on Windows 10.
|
| +#if defined(DEBUG)
|
| + if (IsWindows10OrGreater()) {
|
| + ASSERT(result || (GetLastError() == ERROR_NOT_FOUND));
|
| + }
|
| +#else
|
| + USE(result);
|
| +#endif
|
| }
|
| if (!IsClosing()) {
|
| // Close the socket and set the closing state. This close method can be
|
| @@ -753,6 +761,18 @@ intptr_t Handle::SendTo(const void* buffer,
|
| }
|
|
|
|
|
| +Mutex* StdHandle::stdin_mutex_ = new Mutex();
|
| +StdHandle* StdHandle::stdin_ = NULL;
|
| +
|
| +StdHandle* StdHandle::Stdin(HANDLE handle) {
|
| + MutexLocker ml(stdin_mutex_);
|
| + if (stdin_ == NULL) {
|
| + stdin_ = new StdHandle(handle);
|
| + }
|
| + return stdin_;
|
| +}
|
| +
|
| +
|
| static void WriteFileThread(uword args) {
|
| StdHandle* handle = reinterpret_cast<StdHandle*>(args);
|
| handle->RunWriteLoop();
|
| @@ -845,19 +865,24 @@ intptr_t StdHandle::Write(const void* buffer, intptr_t num_bytes) {
|
|
|
|
|
| void StdHandle::DoClose() {
|
| - MonitorLocker ml(monitor_);
|
| - if (write_thread_exists_) {
|
| - write_thread_running_ = false;
|
| - ml.Notify();
|
| - while (write_thread_exists_) {
|
| - ml.Wait(Monitor::kNoTimeout);
|
| + {
|
| + MonitorLocker ml(monitor_);
|
| + if (write_thread_exists_) {
|
| + write_thread_running_ = false;
|
| + ml.Notify();
|
| + while (write_thread_exists_) {
|
| + ml.Wait(Monitor::kNoTimeout);
|
| + }
|
| + // Join the thread.
|
| + DWORD res = WaitForSingleObject(thread_handle_, INFINITE);
|
| + CloseHandle(thread_handle_);
|
| + ASSERT(res == WAIT_OBJECT_0);
|
| }
|
| - // Join the thread.
|
| - DWORD res = WaitForSingleObject(thread_handle_, INFINITE);
|
| - CloseHandle(thread_handle_);
|
| - ASSERT(res == WAIT_OBJECT_0);
|
| + Handle::DoClose();
|
| }
|
| - Handle::DoClose();
|
| + MutexLocker ml(stdin_mutex_);
|
| + stdin_->Release();
|
| + StdHandle::stdin_ = NULL;
|
| }
|
|
|
|
|
| @@ -1512,7 +1537,6 @@ void EventHandlerImplementation::EventHandlerEntry(uword args) {
|
| }
|
| handler_impl->HandleCompletionOrInterrupt(ok, bytes, key, overlapped);
|
| }
|
| -#endif
|
|
|
| // The eventhandler thread is going down so there should be no more live
|
| // Handles or Sockets.
|
| @@ -1520,9 +1544,13 @@ void EventHandlerImplementation::EventHandlerEntry(uword args) {
|
| // ReferenceCounted<Handle>::instances() == 0;
|
| // However, we cannot at the moment. See the TODO on:
|
| // ClientSocket::IssueDisconnect()
|
| + // Furthermore, if the Dart program references stdin, but does not
|
| + // explicitly close it, then the StdHandle for it will be leaked to here.
|
| + const intptr_t stdin_leaked = (StdHandle::StdinPtr() == NULL) ? 0 : 1;
|
| DEBUG_ASSERT(ReferenceCounted<Handle>::instances() ==
|
| - ClientSocket::disconnecting());
|
| + ClientSocket::disconnecting() + stdin_leaked);
|
| DEBUG_ASSERT(ReferenceCounted<Socket>::instances() == 0);
|
| +#endif // defined(DEBUG)
|
| handler->NotifyShutdownDone();
|
| }
|
|
|
|
|