Index: lldb/trunk/source/Host/common/Host.cpp =================================================================== --- lldb/trunk/source/Host/common/Host.cpp +++ lldb/trunk/source/Host/common/Host.cpp @@ -113,7 +113,7 @@ return ThreadLauncher::LaunchThread(thread_name, MonitorChildProcessThreadFunction, info_ptr, NULL); } -#if !defined(__ANDROID__) && !defined(__ANDROID_NDK__) +#ifndef __linux__ //------------------------------------------------------------------ // Scoped class that will disable thread canceling when it is // constructed, and exception safely restore the previous value it @@ -140,7 +140,32 @@ private: int m_old_state; // Save the old cancelability state. }; -#endif // __ANDROID_NDK__ +#endif // __linux__ + +#ifdef __linux__ +static thread_local volatile sig_atomic_t g_usr1_called; + +static void +SigUsr1Handler (int) +{ + g_usr1_called = 1; +} +#endif // __linux__ + +static bool +CheckForMonitorCancellation() +{ +#ifdef __linux__ + if (g_usr1_called) + { + g_usr1_called = 0; + return true; + } +#else + ::pthread_testcancel (); +#endif + return false; +} static thread_result_t MonitorChildProcessThreadFunction (void *arg) @@ -167,21 +192,29 @@ #endif const int options = __WALL; +#ifdef __linux__ + // This signal is only used to interrupt the thread from waitpid + struct sigaction sigUsr1Action; + memset(&sigUsr1Action, 0, sizeof(sigUsr1Action)); + sigUsr1Action.sa_handler = SigUsr1Handler; + ::sigaction(SIGUSR1, &sigUsr1Action, nullptr); +#endif // __linux__ + while (1) { log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS); if (log) log->Printf("%s ::waitpid (pid = %" PRIi32 ", &status, options = %i)...", function, pid, options); - // Wait for all child processes -#if !defined(__ANDROID__) && !defined(__ANDROID_NDK__) - ::pthread_testcancel (); -#endif + if (CheckForMonitorCancellation ()) + break; + // Get signals from all children with same process group of pid const ::pid_t wait_pid = ::waitpid (pid, &status, options); -#if !defined(__ANDROID__) && !defined(__ANDROID_NDK__) - ::pthread_testcancel (); -#endif + + if (CheckForMonitorCancellation ()) + break; + if (wait_pid == -1) { if (errno == EINTR) @@ -226,7 +259,7 @@ // Scope for pthread_cancel_disabler { -#if !defined(__ANDROID__) && !defined(__ANDROID_NDK__) +#ifndef __linux__ ScopedPThreadCancelDisabler pthread_cancel_disabler; #endif Index: lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.h =================================================================== --- lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.h +++ lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.h @@ -257,7 +257,7 @@ Error &error); /// Attaches to an existing process. Forms the - /// implementation of Process::DoLaunch. + /// implementation of Process::DoAttach void AttachToInferior (lldb::pid_t pid, Error &error); @@ -317,7 +317,7 @@ /// Stops the child monitor thread. void - StopMonitoringChildProcess(); + StopMonitorThread(); /// Stops the operation thread used to attach/launch a process. void Index: lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp =================================================================== --- lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp +++ lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp @@ -35,11 +35,12 @@ #include "lldb/Core/RegisterValue.h" #include "lldb/Core/Scalar.h" #include "lldb/Core/State.h" +#include "lldb/Host/common/NativeRegisterContext.h" #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.h" +#include "lldb/Host/HostNativeThread.h" #include "lldb/Host/ThreadLauncher.h" #include "lldb/Symbol/ObjectFile.h" -#include "lldb/Host/common/NativeRegisterContext.h" #include "lldb/Target/Process.h" #include "lldb/Target/ProcessLaunchInfo.h" #include "lldb/Utility/PseudoTerminal.h" @@ -3557,11 +3558,11 @@ } void -NativeProcessLinux::StopMonitoringChildProcess() +NativeProcessLinux::StopMonitorThread() { if (m_monitor_thread.IsJoinable()) { - m_monitor_thread.Cancel(); + ::pthread_kill(m_monitor_thread.GetNativeThread().GetSystemHandle(), SIGUSR1); m_monitor_thread.Join(nullptr); } } @@ -3569,7 +3570,7 @@ void NativeProcessLinux::StopMonitor() { - StopMonitoringChildProcess(); + StopMonitorThread(); StopCoordinatorThread (); StopOpThread(); sem_destroy(&m_operation_pending); Index: lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.cpp =================================================================== --- lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.cpp +++ lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.cpp @@ -24,6 +24,7 @@ #include "lldb/Core/RegisterValue.h" #include "lldb/Core/Scalar.h" #include "lldb/Host/Host.h" +#include "lldb/Host/HostNativeThread.h" #include "lldb/Host/HostThread.h" #include "lldb/Host/ThreadLauncher.h" #include "lldb/Target/Thread.h" @@ -94,6 +95,8 @@ using namespace lldb_private; +static Operation* EXIT_OPERATION = nullptr; + // FIXME: this code is host-dependent with respect to types and // endianness and needs to be fixed. For example, lldb::addr_t is // hard-coded to uint64_t, but on a 32-bit Linux host, ptrace requires @@ -2335,7 +2338,7 @@ { if (m_monitor_thread.IsJoinable()) { - m_monitor_thread.Cancel(); + ::pthread_kill(m_monitor_thread.GetNativeThread().GetSystemHandle(), SIGUSR1); m_monitor_thread.Join(nullptr); } } @@ -2359,6 +2362,6 @@ if (!m_operation_thread.IsJoinable()) return; - m_operation_thread.Cancel(); + DoOperation(EXIT_OPERATION); m_operation_thread.Join(nullptr); }