diff --git a/runtime/bin/eventhandler.cc b/runtime/bin/eventhandler.cc index 542602f6bde..4d29d95a109 100644 --- a/runtime/bin/eventhandler.cc +++ b/runtime/bin/eventhandler.cc @@ -4,7 +4,9 @@ #include "bin/dartutils.h" #include "bin/eventhandler.h" +#include "bin/lockers.h" #include "bin/socket.h" +#include "bin/thread.h" #include "include/dart_api.h" @@ -57,19 +59,40 @@ void TimeoutQueue::UpdateTimeout(Dart_Port port, int64_t timeout) { static EventHandler* event_handler = NULL; +static Monitor *shutdown_monitor = NULL; void EventHandler::Start() { ASSERT(event_handler == NULL); + shutdown_monitor = new Monitor(); event_handler = new EventHandler(); event_handler->delegate_.Start(event_handler); } +void EventHandler::NotifyShutdownDone() { + MonitorLocker ml(shutdown_monitor); + ml.Notify(); +} + + void EventHandler::Stop() { if (event_handler == NULL) return; - event_handler->delegate_.Shutdown(); + + // Wait until it has stopped. + { + MonitorLocker ml(shutdown_monitor); + + // Signal to event handler that we want it to stop. + event_handler->delegate_.Shutdown(); + ml.Wait(Monitor::kNoTimeout); + } + + // Cleanup + delete event_handler; event_handler = NULL; + delete shutdown_monitor; + shutdown_monitor = NULL; } diff --git a/runtime/bin/eventhandler.h b/runtime/bin/eventhandler.h index 80efaca6577..644c7d44462 100644 --- a/runtime/bin/eventhandler.h +++ b/runtime/bin/eventhandler.h @@ -119,6 +119,11 @@ class EventHandler { delegate_.SendData(id, dart_port, data); } + /** + * Signal to main thread that event handler is done. + */ + void NotifyShutdownDone(); + /** * Start the event-handler. */ diff --git a/runtime/bin/eventhandler_android.cc b/runtime/bin/eventhandler_android.cc index 680bcae7b99..a4ac240047d 100644 --- a/runtime/bin/eventhandler_android.cc +++ b/runtime/bin/eventhandler_android.cc @@ -299,25 +299,27 @@ void EventHandlerImplementation::Poll(uword args) { ThreadSignalBlocker signal_blocker(SIGPROF); static const intptr_t kMaxEvents = 16; struct epoll_event events[kMaxEvents]; - EventHandlerImplementation* handler = - reinterpret_cast(args); - ASSERT(handler != NULL); - while (!handler->shutdown_) { - int64_t millis = handler->GetTimeout(); + EventHandler* handler = reinterpret_cast(args); + EventHandlerImplementation* handler_impl = &handler->delegate_; + ASSERT(handler_impl != NULL); + + while (!handler_impl->shutdown_) { + int64_t millis = handler_impl->GetTimeout(); ASSERT(millis == kInfinityTimeout || millis >= 0); if (millis > kMaxInt32) millis = kMaxInt32; intptr_t result = TEMP_FAILURE_RETRY_NO_SIGNAL_BLOCKER( - epoll_wait(handler->epoll_fd_, events, kMaxEvents, millis)); + epoll_wait(handler_impl->epoll_fd_, events, kMaxEvents, millis)); ASSERT(EAGAIN == EWOULDBLOCK); if (result == -1) { if (errno != EWOULDBLOCK) { perror("Poll failed"); } } else { - handler->HandleTimeout(); - handler->HandleEvents(events, result); + handler_impl->HandleTimeout(); + handler_impl->HandleEvents(events, result); } } + handler->NotifyShutdownDone(); } diff --git a/runtime/bin/eventhandler_linux.cc b/runtime/bin/eventhandler_linux.cc index 97b305b61e3..ba1d88862e6 100644 --- a/runtime/bin/eventhandler_linux.cc +++ b/runtime/bin/eventhandler_linux.cc @@ -315,6 +315,7 @@ void EventHandlerImplementation::Poll(uword args) { EventHandler* handler = reinterpret_cast(args); EventHandlerImplementation* handler_impl = &handler->delegate_; ASSERT(handler_impl != NULL); + while (!handler_impl->shutdown_) { intptr_t result = TEMP_FAILURE_RETRY_NO_SIGNAL_BLOCKER( epoll_wait(handler_impl->epoll_fd_, events, kMaxEvents, -1)); @@ -327,13 +328,13 @@ void EventHandlerImplementation::Poll(uword args) { handler_impl->HandleEvents(events, result); } } - delete handler; + handler->NotifyShutdownDone(); } void EventHandlerImplementation::Start(EventHandler* handler) { int result = Thread::Start(&EventHandlerImplementation::Poll, - reinterpret_cast(handler)); + reinterpret_cast(handler)); if (result != 0) { FATAL1("Failed to start event handler thread %d", result); } diff --git a/runtime/bin/eventhandler_macos.cc b/runtime/bin/eventhandler_macos.cc index 49ec2477e19..29617cd2df2 100644 --- a/runtime/bin/eventhandler_macos.cc +++ b/runtime/bin/eventhandler_macos.cc @@ -358,6 +358,7 @@ void EventHandlerImplementation::EventHandlerEntry(uword args) { EventHandler* handler = reinterpret_cast(args); EventHandlerImplementation* handler_impl = &handler->delegate_; ASSERT(handler_impl != NULL); + while (!handler_impl->shutdown_) { int64_t millis = handler_impl->GetTimeout(); ASSERT(millis == kInfinityTimeout || millis >= 0); @@ -387,14 +388,14 @@ void EventHandlerImplementation::EventHandlerEntry(uword args) { handler_impl->HandleEvents(events, result); } } - delete handler; + handler->NotifyShutdownDone(); } void EventHandlerImplementation::Start(EventHandler* handler) { int result = Thread::Start(&EventHandlerImplementation::EventHandlerEntry, - reinterpret_cast(handler)); + reinterpret_cast(handler)); if (result != 0) { FATAL1("Failed to start event handler thread %d", result); } diff --git a/runtime/bin/eventhandler_win.cc b/runtime/bin/eventhandler_win.cc index fff9d87d9ae..b90332c6efc 100644 --- a/runtime/bin/eventhandler_win.cc +++ b/runtime/bin/eventhandler_win.cc @@ -1295,6 +1295,7 @@ void EventHandlerImplementation::EventHandlerEntry(uword args) { EventHandler* handler = reinterpret_cast(args); EventHandlerImplementation* handler_impl = &handler->delegate_; ASSERT(handler_impl != NULL); + while (!handler_impl->shutdown_) { DWORD bytes; ULONG_PTR key; @@ -1344,13 +1345,13 @@ void EventHandlerImplementation::EventHandlerEntry(uword args) { handler_impl->HandleIOCompletion(bytes, key, overlapped); } } - delete handler; + handler->NotifyShutdownDone(); } void EventHandlerImplementation::Start(EventHandler* handler) { int result = Thread::Start(EventHandlerEntry, - reinterpret_cast(handler)); + reinterpret_cast(handler)); if (result != 0) { FATAL1("Failed to start event handler thread %d", result); }