[Lldb-commits] [lldb] r227924 - Modify ThreadStateCoodrinator in order to resume threads if stop wasn't requested.
Chaoren Lin
chaorenl at google.com
Mon Feb 2 17:51:15 PST 2015
Author: chaoren
Date: Mon Feb 2 19:51:15 2015
New Revision: 227924
URL: http://llvm.org/viewvc/llvm-project?rev=227924&view=rev
Log:
Modify ThreadStateCoodrinator in order to resume threads if stop wasn't requested.
Modified:
lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp
lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.h
lldb/trunk/source/Plugins/Process/Linux/ThreadStateCoordinator.cpp
lldb/trunk/source/Plugins/Process/Linux/ThreadStateCoordinator.h
lldb/trunk/test/functionalities/thread/concurrent_events/TestConcurrentEvents.py
Modified: lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp?rev=227924&r1=227923&r2=227924&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp Mon Feb 2 19:51:15 2015
@@ -166,7 +166,7 @@ namespace
{
Log *const log = GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD);
if (log)
- log->Printf ("NativePlatformLinux::%s %s", __FUNCTION__, error_message.c_str ());
+ log->Printf ("NativeProcessLinux::%s %s", __FUNCTION__, error_message.c_str ());
assert (false && "ThreadStateCoordinator error reported");
}
@@ -1952,7 +1952,7 @@ NativeProcessLinux::MonitorCallback(void
if (exited)
{
if (log)
- log->Printf ("NativeProcessLinux::%s() got exit signal, tid = %" PRIu64 " (%s main thread)", __FUNCTION__, pid, is_main_thread ? "is" : "is not");
+ log->Printf ("NativeProcessLinux::%s() got exit signal(%d) , tid = %" PRIu64 " (%s main thread)", __FUNCTION__, signal, pid, is_main_thread ? "is" : "is not");
// This is a thread that exited. Ensure we're not tracking it anymore.
const bool thread_found = process->StopTrackingThread (pid);
@@ -2111,7 +2111,7 @@ NativeProcessLinux::MonitorSIGTRAP(const
// We can now resume the newly created thread since it is fully created.
NotifyThreadCreateStopped (tid);
m_coordinator_up->RequestThreadResume (tid,
- [=](lldb::tid_t tid_to_resume)
+ [=](lldb::tid_t tid_to_resume, bool supress_signal)
{
reinterpret_cast<NativeThreadLinux*> (new_thread_sp.get ())->SetRunning ();
Resume (tid_to_resume, LLDB_INVALID_SIGNAL_NUMBER);
@@ -2133,7 +2133,7 @@ NativeProcessLinux::MonitorSIGTRAP(const
// In all cases, we can resume the main thread here.
m_coordinator_up->RequestThreadResume (pid,
- [=](lldb::tid_t tid_to_resume)
+ [=](lldb::tid_t tid_to_resume, bool supress_signal)
{
reinterpret_cast<NativeThreadLinux*> (thread_sp.get ())->SetRunning ();
Resume (tid_to_resume, LLDB_INVALID_SIGNAL_NUMBER);
@@ -2237,10 +2237,10 @@ NativeProcessLinux::MonitorSIGTRAP(const
const int signo = static_cast<int> (data);
m_coordinator_up->RequestThreadResume (pid,
- [=](lldb::tid_t tid_to_resume)
+ [=](lldb::tid_t tid_to_resume, bool supress_signal)
{
reinterpret_cast<NativeThreadLinux*> (thread_sp.get ())->SetRunning ();
- Resume (tid_to_resume, signo);
+ Resume (tid_to_resume, (supress_signal) ? LLDB_INVALID_SIGNAL_NUMBER : signo);
},
CoordinatorErrorHandler);
@@ -2253,6 +2253,11 @@ NativeProcessLinux::MonitorSIGTRAP(const
if (log)
log->Printf ("NativeProcessLinux::%s() received trace event, pid = %" PRIu64 " (single stepping)", __FUNCTION__, pid);
+ if (thread_sp)
+ {
+ reinterpret_cast<NativeThreadLinux*> (thread_sp.get ())->SetStoppedBySignal (SIGTRAP);
+ }
+
// This thread is currently stopped.
NotifyThreadStop (pid);
@@ -2260,6 +2265,9 @@ NativeProcessLinux::MonitorSIGTRAP(const
// This would have already happened at the time the Resume() with step operation was signaled.
// At this point, we just need to say we stopped, and the deferred notifcation will fire off
// once all running threads have checked in as stopped.
+ SetCurrentThreadID (pid);
+ // Tell the process we have a stop (from software breakpoint).
+ SetState (StateType::eStateStopped, true);
break;
case SI_KERNEL:
@@ -2338,7 +2346,7 @@ NativeProcessLinux::MonitorSIGTRAP(const
// Ignore these signals until we know more about them.
m_coordinator_up->RequestThreadResume (pid,
- [=](lldb::tid_t tid_to_resume)
+ [=](lldb::tid_t tid_to_resume, bool supress_signal)
{
reinterpret_cast<NativeThreadLinux*> (thread_sp.get ())->SetRunning ();
Resume (tid_to_resume, LLDB_INVALID_SIGNAL_NUMBER);
@@ -2418,7 +2426,7 @@ NativeProcessLinux::MonitorSignal(const
// We can now resume the newly created thread since it is fully created.
NotifyThreadCreateStopped (pid);
m_coordinator_up->RequestThreadResume (pid,
- [=](lldb::tid_t tid_to_resume)
+ [=](lldb::tid_t tid_to_resume, bool supress_signal)
{
reinterpret_cast<NativeThreadLinux*> (thread_sp.get ())->SetRunning ();
Resume (tid_to_resume, LLDB_INVALID_SIGNAL_NUMBER);
@@ -2463,8 +2471,9 @@ NativeProcessLinux::MonitorSignal(const
// An inferior thread just stopped, but was not the primary cause of the process stop.
// Instead, something else (like a breakpoint or step) caused the stop. Mark the
// stop signal as 0 to let lldb know this isn't the important stop.
- reinterpret_cast<NativeThreadLinux*> (thread_sp.get ())->SetStoppedBySignal (0);
+ linux_thread_p->SetStoppedBySignal (0);
SetCurrentThreadID (thread_sp->GetID ());
+ m_coordinator_up->NotifyThreadStop (thread_sp->GetID (), true, CoordinatorErrorHandler);
}
else
{
@@ -2485,10 +2494,9 @@ NativeProcessLinux::MonitorSignal(const
stop_signo,
signal_name);
}
+ // Tell the thread state coordinator about the stop.
+ NotifyThreadStop (thread_sp->GetID ());
}
-
- // Tell the thread state coordinator about the stop.
- NotifyThreadStop (thread_sp->GetID ());
}
// Done handling.
@@ -2498,55 +2506,13 @@ NativeProcessLinux::MonitorSignal(const
if (log)
log->Printf ("NativeProcessLinux::%s() received signal %s", __FUNCTION__, GetUnixSignals ().GetSignalAsCString (signo));
+ // This thread is stopped.
+ NotifyThreadStop (pid);
+
switch (signo)
{
- case SIGSEGV:
- case SIGABRT:
- case SIGILL:
- case SIGFPE:
- case SIGBUS:
- default:
- {
- // This thread is stopped.
- NotifyThreadStop (pid);
-
- // lldb::addr_t fault_addr = reinterpret_cast<lldb::addr_t>(info->si_addr);
-
- // This is just a pre-signal-delivery notification of the incoming signal.
- if (thread_sp)
- reinterpret_cast<NativeThreadLinux*> (thread_sp.get ())->SetStoppedBySignal (signo);
-
- // We can get more details on the exact nature of the crash here.
- // ProcessMessage::CrashReason reason = GetCrashReasonForSIGSEGV(info);
- if (!exited)
- {
- // Send a stop to the debugger after we get all other threads to stop.
- CallAfterRunningThreadsStop (pid,
- [=] (lldb::tid_t signaling_tid)
- {
- SetCurrentThreadID (signaling_tid);
- SetState (StateType::eStateStopped, true);
- });
- }
- else
- {
- // FIXME the process might die right after this - might not ever get stops on any other threads.
- // Send a stop to the debugger after we get all other threads to stop.
- CallAfterRunningThreadsStop (pid,
- [=] (lldb::tid_t signaling_tid)
- {
- SetCurrentThreadID (signaling_tid);
- SetState (StateType::eStateCrashed, true);
- });
- }
- }
- break;
-
case SIGSTOP:
{
- // This thread is stopped.
- NotifyThreadStop (pid);
-
if (log)
{
if (is_from_llgs)
@@ -2558,25 +2524,38 @@ NativeProcessLinux::MonitorSignal(const
// Resume this thread to get the group-stop mechanism to fire off the true group stops.
// This thread will get stopped again as part of the group-stop completion.
m_coordinator_up->RequestThreadResume (pid,
- [=](lldb::tid_t tid_to_resume)
+ [=](lldb::tid_t tid_to_resume, bool supress_signal)
{
reinterpret_cast<NativeThreadLinux*> (thread_sp.get ())->SetRunning ();
// Pass this signal number on to the inferior to handle.
- Resume (tid_to_resume, signo);
+ Resume (tid_to_resume, (supress_signal) ? LLDB_INVALID_SIGNAL_NUMBER : signo);
},
CoordinatorErrorHandler);
-
- // And now we want to signal that we received a SIGSTOP on this thread
- // as soon as all running threads stop (i.e. the group stop sequence completes).
- CallAfterRunningThreadsStop (pid,
- [=] (lldb::tid_t signaling_tid)
- {
- SetCurrentThreadID (signaling_tid);
- SetState (StateType::eStateStopped, true);
- });
}
break;
+ case SIGSEGV:
+ case SIGILL:
+ case SIGFPE:
+ case SIGBUS:
+ if (thread_sp)
+ reinterpret_cast<NativeThreadLinux*>(thread_sp.get())->SetCrashedWithException(
+ signo, reinterpret_cast<lldb::addr_t>(info->si_addr));
+ break;
+ default:
+ // This is just a pre-signal-delivery notification of the incoming signal.
+ if (thread_sp)
+ reinterpret_cast<NativeThreadLinux*> (thread_sp.get ())->SetStoppedBySignal (signo);
+
+ break;
}
+
+ // Send a stop to the debugger after we get all other threads to stop.
+ CallAfterRunningThreadsStop (pid,
+ [=] (lldb::tid_t signaling_tid)
+ {
+ SetCurrentThreadID (signaling_tid);
+ SetState (StateType::eStateStopped, true);
+ });
}
Error
@@ -2593,6 +2572,7 @@ NativeProcessLinux::Resume (const Resume
int deferred_signo = 0;
NativeThreadProtocolSP deferred_signal_thread_sp;
int resume_count = 0;
+ bool stepping = false;
// std::vector<NativeThreadProtocolSP> new_stop_threads;
@@ -2620,11 +2600,11 @@ NativeProcessLinux::Resume (const Resume
// Run the thread, possibly feeding it the signal.
const int signo = action->signal;
m_coordinator_up->RequestThreadResumeAsNeeded (thread_sp->GetID (),
- [=](lldb::tid_t tid_to_resume)
+ [=](lldb::tid_t tid_to_resume, bool supress_signal)
{
reinterpret_cast<NativeThreadLinux*> (thread_sp.get ())->SetRunning ();
// Pass this signal number on to the inferior to handle.
- Resume (tid_to_resume, (signo > 0) ? signo : LLDB_INVALID_SIGNAL_NUMBER);
+ Resume (tid_to_resume, (signo > 0 && !supress_signal) ? signo : LLDB_INVALID_SIGNAL_NUMBER);
},
CoordinatorErrorHandler);
++resume_count;
@@ -2636,31 +2616,14 @@ NativeProcessLinux::Resume (const Resume
// Request the step.
const int signo = action->signal;
m_coordinator_up->RequestThreadResume (thread_sp->GetID (),
- [=](lldb::tid_t tid_to_step)
+ [=](lldb::tid_t tid_to_step, bool supress_signal)
{
reinterpret_cast<NativeThreadLinux*> (thread_sp.get ())->SetStepping ();
- auto step_result = SingleStep (tid_to_step,(signo > 0) ? signo : LLDB_INVALID_SIGNAL_NUMBER);
+ auto step_result = SingleStep (tid_to_step,(signo > 0 && !supress_signal) ? signo : LLDB_INVALID_SIGNAL_NUMBER);
assert (step_result && "SingleStep() failed");
},
CoordinatorErrorHandler);
-
- // The deferred signal tid is the stepping tid.
- // This assumes there is only one stepping tid, or the last stepping tid is a fine choice.
- deferred_signal_tid = thread_sp->GetID ();
- deferred_signal_thread_sp = thread_sp;
-
- // Don't send a stop request to this thread. The thread resume request
- // above will actually run the step thread, and it will finish the step
- // by sending a SIGTRAP with the appropriate bits set. So, the deferred
- // signal call that happens at the end of the loop below needs to let
- // the pending signal handling to *not* send a stop for this thread here
- // since the start/stop step functionality will end up with a stop state.
- // Otherwise, this stepping thread will get sent an erroneous tgkill for
- // with a SIGSTOP signal.
- deferred_signal_skip_tid = thread_sp->GetID ();
-
- // And the stop signal we should apply for it is a SIGTRAP.
- deferred_signo = SIGTRAP;
+ stepping = true;
break;
}
@@ -2684,7 +2647,8 @@ NativeProcessLinux::Resume (const Resume
// If we had any thread stopping, then do a deferred notification of the chosen stop thread id and signal
// after all other running threads have stopped.
- if (deferred_signal_tid != LLDB_INVALID_THREAD_ID)
+ // If there is a stepping thread involved we'll be eventually stopped by SIGTRAP trace signal.
+ if (deferred_signal_tid != LLDB_INVALID_THREAD_ID && !stepping)
{
CallAfterRunningThreadsStopWithSkipTID (deferred_signal_tid,
deferred_signal_skip_tid,
@@ -3894,18 +3858,22 @@ NativeProcessLinux::NotifyThreadDeath (l
void
NativeProcessLinux::NotifyThreadStop (lldb::tid_t tid)
{
- m_coordinator_up->NotifyThreadStop (tid, CoordinatorErrorHandler);
+ m_coordinator_up->NotifyThreadStop (tid, false, CoordinatorErrorHandler);
}
void
NativeProcessLinux::CallAfterRunningThreadsStop (lldb::tid_t tid,
const std::function<void (lldb::tid_t tid)> &call_after_function)
{
+ Log *const log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
+ if (log)
+ log->Printf("NativeProcessLinux::%s tid %" PRIu64, __FUNCTION__, tid);
+
const lldb::pid_t pid = GetID ();
m_coordinator_up->CallAfterRunningThreadsStop (tid,
[=](lldb::tid_t request_stop_tid)
{
- tgkill (pid, request_stop_tid, SIGSTOP);
+ RequestThreadStop(pid, request_stop_tid);
},
call_after_function,
CoordinatorErrorHandler);
@@ -3916,13 +3884,36 @@ NativeProcessLinux::CallAfterRunningThre
lldb::tid_t skip_stop_request_tid,
const std::function<void (lldb::tid_t tid)> &call_after_function)
{
+ Log *const log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
+ if (log)
+ log->Printf("NativeProcessLinux::%s deferred_signal_tid %" PRIu64 ", skip_stop_request_tid %" PRIu64, __FUNCTION__, deferred_signal_tid, skip_stop_request_tid);
+
const lldb::pid_t pid = GetID ();
m_coordinator_up->CallAfterRunningThreadsStopWithSkipTIDs (deferred_signal_tid,
skip_stop_request_tid != LLDB_INVALID_THREAD_ID ? ThreadStateCoordinator::ThreadIDSet {skip_stop_request_tid} : ThreadStateCoordinator::ThreadIDSet (),
[=](lldb::tid_t request_stop_tid)
{
- tgkill (pid, request_stop_tid, SIGSTOP);
+ RequestThreadStop(pid, request_stop_tid);
},
call_after_function,
CoordinatorErrorHandler);
}
+
+lldb_private::Error
+NativeProcessLinux::RequestThreadStop (const lldb::pid_t pid, const lldb::tid_t tid)
+{
+ Log* log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
+ if (log)
+ log->Printf ("NativeProcessLinux::%s requesting thread stop(pid: %" PRIu64 ", tid: %" PRIu64 ")", __FUNCTION__, pid, tid);
+
+ Error err;
+ errno = 0;
+ if (::tgkill (pid, tid, SIGSTOP) != 0)
+ {
+ err.SetErrorToErrno ();
+ if (log)
+ log->Printf ("NativeProcessLinux::%s tgkill(%" PRIu64 ", %" PRIu64 ", SIGSTOP) failed: %s", __FUNCTION__, pid, tid, err.AsCString ());
+ }
+
+ return err;
+}
Modified: lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.h?rev=227924&r1=227923&r2=227924&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.h (original)
+++ lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.h Mon Feb 2 19:51:15 2015
@@ -408,6 +408,9 @@ namespace lldb_private
lldb_private::Error
Detach(lldb::tid_t tid);
+
+ lldb_private::Error
+ RequestThreadStop (const lldb::pid_t pid, const lldb::tid_t tid);
};
} // End lldb_private namespace.
Modified: lldb/trunk/source/Plugins/Process/Linux/ThreadStateCoordinator.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/ThreadStateCoordinator.cpp?rev=227924&r1=227923&r2=227924&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/ThreadStateCoordinator.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Linux/ThreadStateCoordinator.cpp Mon Feb 2 19:51:15 2015
@@ -149,7 +149,7 @@ public:
ProcessEvent(ThreadStateCoordinator &coordinator) override
{
// Validate we know about the deferred trigger thread.
- if (coordinator.m_tid_stop_map.find (m_triggering_tid) == coordinator.m_tid_stop_map.end ())
+ if (!coordinator.IsKnownThread (m_triggering_tid))
{
// We don't know about this thread. This is an error condition.
std::ostringstream error_message;
@@ -172,7 +172,7 @@ public:
if (m_wait_for_stop_tids.empty ())
{
- // We're not waiting for any threads. Fire off the deferred signal delivery event.
+ // We're not waiting for any threads. Fire off the deferred signal delivery event.
NotifyNow ();
}
else
@@ -235,7 +235,7 @@ private:
}
bool
- RequestStopOnAllSpecifiedThreads (const ThreadStateCoordinator &coordinator)
+ RequestStopOnAllSpecifiedThreads (ThreadStateCoordinator &coordinator)
{
// Request a stop for all the thread stops that need to be stopped
// and are not already known to be stopped. Keep a list of all the
@@ -246,8 +246,8 @@ private:
{
// Validate we know about all tids for which we must first receive a stop before
// triggering the deferred stop notification.
- auto find_it = coordinator.m_tid_stop_map.find (tid);
- if (find_it == coordinator.m_tid_stop_map.end ())
+ auto find_it = coordinator.m_tid_map.find (tid);
+ if (find_it == coordinator.m_tid_map.end ())
{
// This is an error. We shouldn't be asking for waiting pids that aren't known.
// NOTE: we may be stripping out the specification of wait tids and handle this
@@ -261,9 +261,10 @@ private:
}
// If the pending stop thread is currently running, we need to send it a stop request.
- if (!find_it->second)
+ if (find_it->second.m_state == ThreadState::Running)
{
m_request_thread_stop_function (tid);
+ RequestThreadStop (tid, find_it->second);
sent_tids.insert (tid);
}
}
@@ -278,17 +279,17 @@ private:
}
void
- RequestStopOnAllRunningThreads (const ThreadStateCoordinator &coordinator)
+ RequestStopOnAllRunningThreads (ThreadStateCoordinator &coordinator)
{
// Request a stop for all the thread stops that need to be stopped
// and are not already known to be stopped. Keep a list of all the
// threads from which we still need to hear a stop reply.
ThreadIDSet sent_tids;
- for (auto it = coordinator.m_tid_stop_map.begin(); it != coordinator.m_tid_stop_map.end(); ++it)
+ for (auto it = coordinator.m_tid_map.begin(); it != coordinator.m_tid_map.end(); ++it)
{
// We only care about threads not stopped.
- const bool running = !it->second;
+ const bool running = it->second.m_state == ThreadState::Running;
if (running)
{
const lldb::tid_t tid = it->first;
@@ -296,7 +297,7 @@ private:
// Request this thread stop if the tid stop request is not explicitly ignored.
const bool skip_stop_request = m_skip_stop_request_tids.count (tid) > 0;
if (!skip_stop_request)
- m_request_thread_stop_function (tid);
+ RequestThreadStop (tid, it->second);
// Even if we skipped sending the stop request for other reasons (like stepping),
// we still need to wait for that stepping thread to notify completion/stop.
@@ -308,6 +309,13 @@ private:
m_wait_for_stop_tids.swap (sent_tids);
}
+ void
+ RequestThreadStop (lldb::tid_t tid, ThreadContext& context)
+ {
+ m_request_thread_stop_function (tid);
+ context.m_stop_requested = true;
+ }
+
const lldb::tid_t m_triggering_tid;
ThreadIDSet m_wait_for_stop_tids;
const ThreadIDSet m_original_wait_for_stop_tids;
@@ -348,9 +356,11 @@ class ThreadStateCoordinator::EventThrea
{
public:
EventThreadStopped (lldb::tid_t tid,
+ bool initiated_by_llgs,
const ErrorFunction &error_function):
EventBase (),
m_tid (tid),
+ m_initiated_by_llgs (initiated_by_llgs),
m_error_function (error_function)
{
}
@@ -358,7 +368,7 @@ public:
EventLoopResult
ProcessEvent(ThreadStateCoordinator &coordinator) override
{
- coordinator.ThreadDidStop (m_tid, m_error_function);
+ coordinator.ThreadDidStop (m_tid, m_initiated_by_llgs, m_error_function);
return eventLoopResultContinue;
}
@@ -373,6 +383,7 @@ public:
private:
const lldb::tid_t m_tid;
+ const bool m_initiated_by_llgs;
ErrorFunction m_error_function;
};
@@ -453,7 +464,7 @@ class ThreadStateCoordinator::EventReque
{
public:
EventRequestResume (lldb::tid_t tid,
- const ThreadIDFunction &request_thread_resume_function,
+ const ResumeThreadFunction &request_thread_resume_function,
const ErrorFunction &error_function,
bool error_when_already_running):
EventBase (),
@@ -468,8 +479,8 @@ public:
ProcessEvent(ThreadStateCoordinator &coordinator) override
{
// Ensure we know about the thread.
- auto find_it = coordinator.m_tid_stop_map.find (m_tid);
- if (find_it == coordinator.m_tid_stop_map.end ())
+ auto find_it = coordinator.m_tid_map.find (m_tid);
+ if (find_it == coordinator.m_tid_map.end ())
{
// We don't know about this thread. This is an error condition.
std::ostringstream error_message;
@@ -477,9 +488,9 @@ public:
m_error_function (error_message.str ());
return eventLoopResultContinue;
}
-
+ auto& context = find_it->second;
// Tell the thread to resume if we don't already think it is running.
- const bool is_stopped = find_it->second;
+ const bool is_stopped = context.m_state == ThreadState::Stopped;
if (!is_stopped)
{
// It's not an error, just a log, if the m_already_running_no_error flag is set.
@@ -532,10 +543,11 @@ public:
// Request a resume. We expect this to be synchronous and the system
// to reflect it is running after this completes.
- m_request_thread_resume_function (m_tid);
+ m_request_thread_resume_function (m_tid, false);
// Now mark it is running.
- find_it->second = false;
+ context.m_state = ThreadState::Running;
+ context.m_request_resume_function = m_request_thread_resume_function;
return eventLoopResultContinue;
}
@@ -551,7 +563,7 @@ public:
private:
const lldb::tid_t m_tid;
- ThreadIDFunction m_request_thread_resume_function;
+ ResumeThreadFunction m_request_thread_resume_function;
ErrorFunction m_error_function;
const bool m_error_when_already_running;
};
@@ -563,7 +575,7 @@ ThreadStateCoordinator::ThreadStateCoord
m_event_queue (),
m_queue_condition (),
m_queue_mutex (),
- m_tid_stop_map (),
+ m_tid_map (),
m_log_event_processing (false)
{
}
@@ -660,11 +672,11 @@ ThreadStateCoordinator::CallAfterRunning
void
-ThreadStateCoordinator::ThreadDidStop (lldb::tid_t tid, ErrorFunction &error_function)
+ThreadStateCoordinator::ThreadDidStop (lldb::tid_t tid, bool initiated_by_llgs, ErrorFunction &error_function)
{
// Ensure we know about the thread.
- auto find_it = m_tid_stop_map.find (tid);
- if (find_it == m_tid_stop_map.end ())
+ auto find_it = m_tid_map.find (tid);
+ if (find_it == m_tid_map.end ())
{
// We don't know about this thread. This is an error condition.
std::ostringstream error_message;
@@ -674,7 +686,10 @@ ThreadStateCoordinator::ThreadDidStop (l
}
// Update the global list of known thread states. This one is definitely stopped.
- find_it->second = true;
+ auto& context = find_it->second;
+ const auto stop_was_requested = context.m_stop_requested;
+ context.m_state = ThreadState::Stopped;
+ context.m_stop_requested = false;
// If we have a pending notification, remove this from the set.
EventCallAfterThreadsStop *const call_after_event = GetPendingThreadStopNotification ();
@@ -687,14 +702,23 @@ ThreadStateCoordinator::ThreadDidStop (l
m_pending_notification_sp.reset ();
}
}
+
+ if (initiated_by_llgs && context.m_request_resume_function && !stop_was_requested)
+ {
+ // We can end up here if stop was initiated by LLGS but by this time a
+ // thread stop has occurred - maybe initiated by another event.
+ Log ("Resuming thread %" PRIu64 " since stop wasn't requested", tid);
+ context.m_request_resume_function (tid, true);
+ context.m_state = ThreadState::Running;
+ }
}
void
ThreadStateCoordinator::ThreadWasCreated (lldb::tid_t tid, bool is_stopped, ErrorFunction &error_function)
{
// Ensure we don't already know about the thread.
- auto find_it = m_tid_stop_map.find (tid);
- if (find_it != m_tid_stop_map.end ())
+ auto find_it = m_tid_map.find (tid);
+ if (find_it != m_tid_map.end ())
{
// We already know about this thread. This is an error condition.
std::ostringstream error_message;
@@ -704,7 +728,9 @@ ThreadStateCoordinator::ThreadWasCreated
}
// Add the new thread to the stop map.
- m_tid_stop_map[tid] = is_stopped;
+ ThreadContext ctx;
+ ctx.m_state = (is_stopped) ? ThreadState::Stopped : ThreadState::Running;
+ m_tid_map[tid] = std::move(ctx);
EventCallAfterThreadsStop *const call_after_event = GetPendingThreadStopNotification ();
if (call_after_event && !is_stopped)
@@ -719,8 +745,8 @@ void
ThreadStateCoordinator::ThreadDidDie (lldb::tid_t tid, ErrorFunction &error_function)
{
// Ensure we know about the thread.
- auto find_it = m_tid_stop_map.find (tid);
- if (find_it == m_tid_stop_map.end ())
+ auto find_it = m_tid_map.find (tid);
+ if (find_it == m_tid_map.end ())
{
// We don't know about this thread. This is an error condition.
std::ostringstream error_message;
@@ -732,7 +758,7 @@ ThreadStateCoordinator::ThreadDidDie (ll
// Update the global list of known thread states. While this one is stopped, it is also dead.
// So stop tracking it. We assume the user of this coordinator will not keep trying to add
// dependencies on a thread after it is known to be dead.
- m_tid_stop_map.erase (find_it);
+ m_tid_map.erase (find_it);
// If we have a pending notification, remove this from the set.
EventCallAfterThreadsStop *const call_after_event = GetPendingThreadStopNotification ();
@@ -757,7 +783,7 @@ ThreadStateCoordinator::ResetNow ()
// The caller is expected to reset thread states for all threads, and we
// will assume anything we haven't heard about is running and requires a
// stop.
- m_tid_stop_map.clear ();
+ m_tid_map.clear ();
}
void
@@ -773,27 +799,26 @@ ThreadStateCoordinator::Log (const char
void
ThreadStateCoordinator::NotifyThreadStop (lldb::tid_t tid,
+ bool initiated_by_llgs,
const ErrorFunction &error_function)
{
- EnqueueEvent (EventBaseSP (new EventThreadStopped (tid, error_function)));
+ EnqueueEvent (EventBaseSP (new EventThreadStopped (tid, initiated_by_llgs, error_function)));
}
void
ThreadStateCoordinator::RequestThreadResume (lldb::tid_t tid,
- const ThreadIDFunction &request_thread_resume_function,
+ const ResumeThreadFunction &request_thread_resume_function,
const ErrorFunction &error_function)
{
- const bool error_when_already_running = true;
- EnqueueEvent (EventBaseSP (new EventRequestResume (tid, request_thread_resume_function, error_function, error_when_already_running)));
+ EnqueueEvent (EventBaseSP (new EventRequestResume (tid, request_thread_resume_function, error_function, true)));
}
void
ThreadStateCoordinator::RequestThreadResumeAsNeeded (lldb::tid_t tid,
- const ThreadIDFunction &request_thread_resume_function,
+ const ResumeThreadFunction &request_thread_resume_function,
const ErrorFunction &error_function)
{
- const bool error_when_already_running = false;
- EnqueueEvent (EventBaseSP (new EventRequestResume (tid, request_thread_resume_function, error_function, error_when_already_running)));
+ EnqueueEvent (EventBaseSP (new EventRequestResume (tid, request_thread_resume_function, error_function, false)));
}
void
@@ -880,3 +905,9 @@ ThreadStateCoordinator::GetPendingThread
{
return static_cast<EventCallAfterThreadsStop*> (m_pending_notification_sp.get ());
}
+
+bool
+ThreadStateCoordinator::IsKnownThread (lldb::tid_t tid) const
+{
+ return m_tid_map.find (tid) != m_tid_map.end ();
+}
Modified: lldb/trunk/source/Plugins/Process/Linux/ThreadStateCoordinator.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/ThreadStateCoordinator.h?rev=227924&r1=227923&r2=227924&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/ThreadStateCoordinator.h (original)
+++ lldb/trunk/source/Plugins/Process/Linux/ThreadStateCoordinator.h Mon Feb 2 19:51:15 2015
@@ -38,6 +38,7 @@ namespace lldb_private
typedef std::function<void (lldb::tid_t tid)> ThreadIDFunction;
typedef std::function<void (const char *format, va_list args)> LogFunction;
typedef std::function<void (const std::string &error_message)> ErrorFunction;
+ typedef std::function<void (lldb::tid_t tid, bool supress_signal)> ResumeThreadFunction;
// Constructors.
ThreadStateCoordinator (const LogFunction &log_function);
@@ -98,6 +99,7 @@ namespace lldb_private
// already think it is stopped.
void
NotifyThreadStop (lldb::tid_t tid,
+ bool initiated_by_llgs,
const ErrorFunction &error_function);
// Request that the given thread id should have the request_thread_resume_function
@@ -106,7 +108,7 @@ namespace lldb_private
// a thread that is already in a running state.
void
RequestThreadResume (lldb::tid_t tid,
- const ThreadIDFunction &request_thread_resume_function,
+ const ResumeThreadFunction &request_thread_resume_function,
const ErrorFunction &error_function);
// Request that the given thread id should have the request_thread_resume_function
@@ -115,7 +117,7 @@ namespace lldb_private
// does not trigger an error in that case.
void
RequestThreadResumeAsNeeded (lldb::tid_t tid,
- const ThreadIDFunction &request_thread_resume_function,
+ const ResumeThreadFunction &request_thread_resume_function,
const ErrorFunction &error_function);
// Indicate the calling process did an exec and that the thread state
@@ -160,7 +162,19 @@ namespace lldb_private
typedef std::queue<EventBaseSP> QueueType;
- typedef std::unordered_map<lldb::tid_t, bool> TIDBoolMap;
+ enum class ThreadState
+ {
+ Running,
+ Stopped
+ };
+
+ struct ThreadContext
+ {
+ ThreadState m_state;
+ bool m_stop_requested = false;
+ ResumeThreadFunction m_request_resume_function;
+ };
+ typedef std::unordered_map<lldb::tid_t, ThreadContext> TIDContextMap;
// Private member functions.
@@ -174,7 +188,7 @@ namespace lldb_private
SetPendingNotification (const EventBaseSP &event_sp);
void
- ThreadDidStop (lldb::tid_t tid, ErrorFunction &error_function);
+ ThreadDidStop (lldb::tid_t tid, bool initiated_by_llgs, ErrorFunction &error_function);
void
ThreadWasCreated (lldb::tid_t tid, bool is_stopped, ErrorFunction &error_function);
@@ -185,6 +199,9 @@ namespace lldb_private
void
ResetNow ();
+ bool
+ IsKnownThread(lldb::tid_t tid) const;
+
void
Log (const char *format, ...);
@@ -204,8 +221,8 @@ namespace lldb_private
EventBaseSP m_pending_notification_sp;
- // Maps known TIDs to stop (true) or not-stopped (false) state.
- TIDBoolMap m_tid_stop_map;
+ // Maps known TIDs to ThreadContext.
+ TIDContextMap m_tid_map;
bool m_log_event_processing;
};
Modified: lldb/trunk/test/functionalities/thread/concurrent_events/TestConcurrentEvents.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/thread/concurrent_events/TestConcurrentEvents.py?rev=227924&r1=227923&r2=227924&view=diff
==============================================================================
--- lldb/trunk/test/functionalities/thread/concurrent_events/TestConcurrentEvents.py (original)
+++ lldb/trunk/test/functionalities/thread/concurrent_events/TestConcurrentEvents.py Mon Feb 2 19:51:15 2015
@@ -372,7 +372,7 @@ class ConcurrentEventsTestCase(TestBase)
"""
return self.finish_breakpoint.GetHitCount() > 0 or \
self.crash_count > 0 or \
- self.inferior_process.GetState == lldb.eStateExited
+ self.inferior_process.GetState() == lldb.eStateExited
def do_thread_actions(self,
num_breakpoint_threads = 0,
More information about the lldb-commits
mailing list