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
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)
#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)
// Scope for pthread_cancel_disabler
{
-#if !defined(__ANDROID__) && !defined(__ANDROID_NDK__)
+#ifndef __linux__
ScopedPThreadCancelDisabler pthread_cancel_disabler;
#endif
#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"
}
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);
}
}
void
NativeProcessLinux::StopMonitor()
{
- StopMonitoringChildProcess();
+ StopMonitorThread();
StopCoordinatorThread ();
StopOpThread();
sem_destroy(&m_operation_pending);
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);
/// Stops the child monitor thread.
void
- StopMonitoringChildProcess();
+ StopMonitorThread();
/// Stops the operation thread used to attach/launch a process.
void
#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"
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
{
if (m_monitor_thread.IsJoinable())
{
- m_monitor_thread.Cancel();
+ ::pthread_kill(m_monitor_thread.GetNativeThread().GetSystemHandle(), SIGUSR1);
m_monitor_thread.Join(nullptr);
}
}
if (!m_operation_thread.IsJoinable())
return;
- m_operation_thread.Cancel();
+ DoOperation(EXIT_OPERATION);
m_operation_thread.Join(nullptr);
}