From 43f2d971915408d168cd4d952de764acecd23fca Mon Sep 17 00:00:00 2001 From: Tamas Berghammer Date: Wed, 4 Mar 2015 11:10:03 +0000 Subject: Fix deadlock in operation thread in NativeProcessLinux The deadlock occurred when the Attach or the Launch operation failed for any reason. Differential revision: http://reviews.llvm.org/D8030 llvm-svn: 231231 --- .../Plugins/Process/Linux/NativeProcessLinux.cpp | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) (limited to 'lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp') diff --git a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp index 9bf8a145237c..78b98f29d36d 100644 --- a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp +++ b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp @@ -143,6 +143,8 @@ namespace using namespace lldb; using namespace lldb_private; + static void * const EXIT_OPERATION = nullptr; + const UnixSignals& GetUnixSignals () { @@ -3371,14 +3373,11 @@ NativeProcessLinux::ServeOperation(OperationArgs *args) assert(false && "Unexpected errno from sem_wait"); } - // nullptr as operation means the operation thread should exit. Cancel() can't be used - // because it is not supported on android. - if (!monitor->m_operation) - { - // notify calling thread that operation is complete - sem_post(&monitor->m_operation_done); + // EXIT_OPERATION used to stop the operation thread because Cancel() isn't supported on + // android. We don't have to send a post to the m_operation_done semaphore because in this + // case the synchronization is achieved by a Join() call + if (monitor->m_operation == EXIT_OPERATION) break; - } reinterpret_cast(monitor->m_operation)->Execute(monitor); @@ -3397,6 +3396,11 @@ NativeProcessLinux::DoOperation(void *op) // notify operation thread that an operation is ready to be processed sem_post(&m_operation_pending); + // Don't wait for the operation to complete in case of an exit operation. The operation thread + // will exit without posting to the semaphore + if (m_operation == EXIT_OPERATION) + return; + // wait for operation to complete while (sem_wait(&m_operation_done)) { @@ -3565,9 +3569,9 @@ NativeProcessLinux::StopMonitoringChildProcess() void NativeProcessLinux::StopMonitor() { - StopOpThread(); StopMonitoringChildProcess(); StopCoordinatorThread (); + StopOpThread(); sem_destroy(&m_operation_pending); sem_destroy(&m_operation_done); @@ -3584,7 +3588,7 @@ NativeProcessLinux::StopOpThread() if (!m_operation_thread.IsJoinable()) return; - DoOperation(nullptr); // nullptr as operation ask the operation thread to exit + DoOperation(EXIT_OPERATION); m_operation_thread.Join(nullptr); } -- cgit v1.2.3