Index: runtime/bin/eventhandler_win.cc |
diff --git a/runtime/bin/eventhandler_win.cc b/runtime/bin/eventhandler_win.cc |
index db698a3c8831e637cb17e15fbeef1c242548d152..05511285b0f7a714462756912c340d50bfd1eda8 100644 |
--- a/runtime/bin/eventhandler_win.cc |
+++ b/runtime/bin/eventhandler_win.cc |
@@ -121,12 +121,16 @@ Handle::Handle(intptr_t handle) |
pending_read_(NULL), |
pending_write_(NULL), |
last_error_(NOERROR), |
- flags_(0) { |
+ flags_(0), |
+ read_thread_id_(Thread::kInvalidThreadId), |
+ read_thread_exists_(false), |
+ read_thread_monitor_(new Monitor()) { |
InitializeCriticalSection(&cs_); |
} |
Handle::~Handle() { |
+ delete read_thread_monitor_; |
DeleteCriticalSection(&cs_); |
} |
@@ -197,6 +201,20 @@ void Handle::ReadComplete(OverlappedBuffer* buffer) { |
OverlappedBuffer::DisposeBuffer(buffer); |
} |
pending_read_ = NULL; |
+ |
+ // Join the Reader thread if there is one. |
+ ThreadId to_join; |
+ { |
+ MonitorLocker ml(read_thread_monitor_); |
+ while (read_thread_exists_) { |
+ ml.Wait(); |
+ } |
+ to_join = read_thread_id_; |
+ read_thread_id = Thread::kInvalidThreadId; |
+ } |
+ if (to_join != Thread::kInvalidThreadId) { |
+ Thread::Join(to_join); |
+ } |
} |
@@ -223,6 +241,12 @@ static void ReadFileThread(uword args) { |
void Handle::ReadSyncCompleteAsync() { |
ASSERT(pending_read_ != NULL); |
ASSERT(pending_read_->GetBufferSize() >= kStdOverlappedBufferSize); |
+ { |
+ MonitorLocker ml(read_thread_monitor_); |
+ read_thread_id_ = Thread::GetCurrentThreadId(); |
+ read_thread_exists_ = true; |
+ ml.Notify(); |
+ } |
DWORD buffer_size = pending_read_->GetBufferSize(); |
if (GetFileType(handle_) == FILE_TYPE_CHAR) { |
@@ -245,6 +269,11 @@ void Handle::ReadSyncCompleteAsync() { |
if (!ok) { |
FATAL("PostQueuedCompletionStatus failed"); |
} |
+ { |
+ MonitorLocker ml(read_thread_monitor_); |
+ read_thread_exists_ = false; |
+ ml.Notify(); |
+ } |
} |
@@ -277,6 +306,13 @@ bool Handle::IssueRead() { |
if (result != 0) { |
FATAL1("Failed to start read file thread %d", result); |
} |
+ { |
+ MonitorLocker ml(read_thread_monitor_); |
+ while (!read_thread_exists_) { |
+ ml.Wait(); |
+ } |
+ ASSERT(read_thread_id_ != Thread::kInvalidThreadId); |
+ } |
return true; |
} |
} |
@@ -677,6 +713,7 @@ static void WriteFileThread(uword args) { |
void StdHandle::RunWriteLoop() { |
write_monitor_->Enter(); |
write_thread_running_ = true; |
+ thread_id_ = Thread::GetCurrentThreadId(); |
// Notify we have started. |
write_monitor_->Notify(); |
@@ -762,6 +799,7 @@ void StdHandle::DoClose() { |
while (write_thread_exists_) { |
locker.Wait(Monitor::kNoTimeout); |
} |
+ Thread::Join(thread_id_); |
} |
Handle::DoClose(); |
} |
@@ -1278,6 +1316,8 @@ void EventHandlerImplementation::HandleIOCompletion(DWORD bytes, |
EventHandlerImplementation::EventHandlerImplementation() { |
+ startup_monitor_ = new Monitor(); |
+ handler_thread_id_ = Thread::kInvalidThreadId; |
completion_port_ = |
CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL, 1); |
if (completion_port_ == NULL) { |
@@ -1288,6 +1328,8 @@ EventHandlerImplementation::EventHandlerImplementation() { |
EventHandlerImplementation::~EventHandlerImplementation() { |
+ Thread::Join(handler_thread_id_); |
+ delete startup_monitor_; |
CloseHandle(completion_port_); |
} |
@@ -1322,6 +1364,12 @@ void EventHandlerImplementation::EventHandlerEntry(uword args) { |
EventHandlerImplementation* handler_impl = &handler->delegate_; |
ASSERT(handler_impl != NULL); |
+ { |
+ MonitorLocker ml(handler_impl->startup_monitor_); |
+ handler_impl->handler_thread_id_ = Thread::GetCurrentThreadId(); |
+ ml.Notify(); |
+ } |
+ |
while (!handler_impl->shutdown_) { |
DWORD bytes; |
ULONG_PTR key; |
@@ -1382,6 +1430,13 @@ void EventHandlerImplementation::Start(EventHandler* handler) { |
FATAL1("Failed to start event handler thread %d", result); |
} |
+ { |
+ MonitorLocker ml(startup_monitor_); |
+ while (handler_thread_id_ == Thread::kInvalidThreadId) { |
+ ml.Wait(); |
+ } |
+ } |
+ |
// Initialize Winsock32 |
if (!Socket::Initialize()) { |
FATAL("Failed to initialized Windows sockets"); |