From 0cbf0b13e74a1334cd318517789f4c692faf524a Mon Sep 17 00:00:00 2001 From: Tamas Berghammer Date: Fri, 13 Mar 2015 11:16:03 +0000 Subject: [PATCH] Add code to exit the NativeProcessLinux Monitor thread on android This CL change the logic used to terminate the monitor thread of NativeProcessLinux to use a signal instead of pthread_cancel as pthread_cancel is not supported on android. Differential revision: http://reviews.llvm.org/D8205 llvm-svn: 232155 --- lldb/source/Host/common/Host.cpp | 53 ++++++++++++++++++---- .../Plugins/Process/Linux/NativeProcessLinux.cpp | 9 ++-- .../Plugins/Process/Linux/NativeProcessLinux.h | 4 +- .../Plugins/Process/Linux/ProcessMonitor.cpp | 7 ++- 4 files changed, 55 insertions(+), 18 deletions(-) diff --git a/lldb/source/Host/common/Host.cpp b/lldb/source/Host/common/Host.cpp index 6b237ce..32b002f 100644 --- a/lldb/source/Host/common/Host.cpp +++ b/lldb/source/Host/common/Host.cpp @@ -113,7 +113,7 @@ Host::StartMonitoringChildProcess(Host::MonitorChildProcessCallback callback, vo 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 @@ public: 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 @@ MonitorChildProcessThreadFunction (void *arg) #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 @@ MonitorChildProcessThreadFunction (void *arg) // Scope for pthread_cancel_disabler { -#if !defined(__ANDROID__) && !defined(__ANDROID_NDK__) +#ifndef __linux__ ScopedPThreadCancelDisabler pthread_cancel_disabler; #endif diff --git a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp index 9c7198e..7c9b32b 100644 --- a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp +++ b/lldb/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 @@ NativeProcessLinux::DupDescriptor(const char *path, int fd, int flags) } 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 @@ NativeProcessLinux::StopMonitoringChildProcess() void NativeProcessLinux::StopMonitor() { - StopMonitoringChildProcess(); + StopMonitorThread(); StopCoordinatorThread (); StopOpThread(); sem_destroy(&m_operation_pending); diff --git a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.h b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.h index 0f0366a..a2ffd6c 100644 --- a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.h +++ b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.h @@ -257,7 +257,7 @@ namespace lldb_private 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 @@ namespace lldb_private /// Stops the child monitor thread. void - StopMonitoringChildProcess(); + StopMonitorThread(); /// Stops the operation thread used to attach/launch a process. void diff --git a/lldb/source/Plugins/Process/Linux/ProcessMonitor.cpp b/lldb/source/Plugins/Process/Linux/ProcessMonitor.cpp index fcfda216..00d4f44 100644 --- a/lldb/source/Plugins/Process/Linux/ProcessMonitor.cpp +++ b/lldb/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 @@ ProcessMonitor::StopMonitoringChildProcess() { 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 @@ ProcessMonitor::StopOpThread() if (!m_operation_thread.IsJoinable()) return; - m_operation_thread.Cancel(); + DoOperation(EXIT_OPERATION); m_operation_thread.Join(nullptr); } -- 2.7.4