Skip to content

Commit 564f13e

Browse files
committed
[lldb] Remove ProcessRunLock::TrySetRunning (llvm#135455)
I traced the issue reported by Caroline and Pavel in llvm#134757 back to the call to ProcessRunLock::TrySetRunning. When that fails, we get a somewhat misleading error message: > process resume at entry point failed: Resume request failed - process still running. This is incorrect: the problem was not that the process was in a running state, but rather that the RunLock was being held by another thread (i.e. the Statusline). TrySetRunning would return false in both cases and the call site only accounted for the former. Besides the odd semantics, the current implementation is inherently race-y and I believe incorrect. If someone is holding the RunLock, the resume call should block, rather than give up, and with the lock held, switch the running state and report the old running state. This patch removes ProcessRunLock::TrySetRunning and updates all callers to use ProcessRunLock::SetRunning instead. To support that, ProcessRunLock::SetRunning (and ProcessRunLock::SetStopped, for consistency) now report whether the process was stopped or running respectively. Previously, both methods returned true unconditionally. The old code has been around pretty much pretty much forever, there's nothing in the git history to indicate that this was done purposely to solve a particular issue. I've tested this on both Linux and macOS and confirmed that this solves the statusline issue. A big thank you to Jim for reviewing my proposed solution offline and trying to poke holes in it. (cherry picked from commit d792094)
1 parent 8e2f173 commit 564f13e

File tree

4 files changed

+39
-68
lines changed

4 files changed

+39
-68
lines changed

lldb/include/lldb/Host/ProcessRunLock.h

+6-1
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,13 @@ class ProcessRunLock {
2929

3030
bool ReadTryLock();
3131
bool ReadUnlock();
32+
33+
/// Set the process to running. Returns true if the process was stopped.
34+
/// Return false if the process was running.
3235
bool SetRunning();
33-
bool TrySetRunning();
36+
37+
/// Set the process to stopped. Returns true if the process was running.
38+
/// Returns false if the process was stopped.
3439
bool SetStopped();
3540

3641
class ProcessRunLocker {

lldb/source/Host/common/ProcessRunLock.cpp

+6-15
Original file line numberDiff line numberDiff line change
@@ -37,29 +37,20 @@ bool ProcessRunLock::ReadUnlock() {
3737

3838
bool ProcessRunLock::SetRunning() {
3939
::pthread_rwlock_wrlock(&m_rwlock);
40+
bool was_stopped = !m_running;
4041
m_running = true;
4142
::pthread_rwlock_unlock(&m_rwlock);
42-
return true;
43-
}
44-
45-
bool ProcessRunLock::TrySetRunning() {
46-
bool r;
47-
48-
if (::pthread_rwlock_trywrlock(&m_rwlock) == 0) {
49-
r = !m_running;
50-
m_running = true;
51-
::pthread_rwlock_unlock(&m_rwlock);
52-
return r;
53-
}
54-
return false;
43+
return was_stopped;
5544
}
5645

5746
bool ProcessRunLock::SetStopped() {
5847
::pthread_rwlock_wrlock(&m_rwlock);
48+
bool was_running = m_running;
5949
m_running = false;
6050
::pthread_rwlock_unlock(&m_rwlock);
61-
return true;
62-
}
51+
return was_running;
6352
}
6453

54+
} // namespace lldb_private
55+
6556
#endif

lldb/source/Host/windows/ProcessRunLock.cpp

+4-12
Original file line numberDiff line numberDiff line change
@@ -58,24 +58,16 @@ bool ProcessRunLock::ReadUnlock() { return ::ReadUnlock(m_rwlock); }
5858

5959
bool ProcessRunLock::SetRunning() {
6060
WriteLock(m_rwlock);
61+
bool was_stopped = !m_running;
6162
m_running = true;
6263
WriteUnlock(m_rwlock);
63-
return true;
64-
}
65-
66-
bool ProcessRunLock::TrySetRunning() {
67-
if (WriteTryLock(m_rwlock)) {
68-
bool was_running = m_running;
69-
m_running = true;
70-
WriteUnlock(m_rwlock);
71-
return !was_running;
72-
}
73-
return false;
64+
return was_stopped;
7465
}
7566

7667
bool ProcessRunLock::SetStopped() {
7768
WriteLock(m_rwlock);
69+
bool was_running = m_running;
7870
m_running = false;
7971
WriteUnlock(m_rwlock);
80-
return true;
72+
return was_running;
8173
}

lldb/source/Target/Process.cpp

+23-40
Original file line numberDiff line numberDiff line change
@@ -614,9 +614,7 @@ void Process::Finalize(bool destructing) {
614614
// contain events that have ProcessSP values in them which can keep this
615615
// process around forever. These events need to be cleared out.
616616
m_private_state_listener_sp->Clear();
617-
m_public_run_lock.TrySetRunning(); // This will do nothing if already locked
618617
m_public_run_lock.SetStopped();
619-
m_private_run_lock.TrySetRunning(); // This will do nothing if already locked
620618
m_private_run_lock.SetStopped();
621619
m_structured_data_plugin_map.clear();
622620
}
@@ -1466,11 +1464,11 @@ void Process::SetPublicState(StateType new_state, bool restarted) {
14661464
Status Process::Resume() {
14671465
Log *log(GetLog(LLDBLog::State | LLDBLog::Process));
14681466
LLDB_LOGF(log, "(plugin = %s) -- locking run lock", GetPluginName().data());
1469-
if (!m_public_run_lock.TrySetRunning()) {
1470-
LLDB_LOGF(log, "(plugin = %s) -- TrySetRunning failed, not resuming.",
1471-
GetPluginName().data());
1467+
if (!m_public_run_lock.SetRunning()) {
1468+
LLDB_LOGF(log, "(plugin = %s) -- SetRunning failed, not resuming.",
1469+
GetPluginName().data());
14721470
return Status::FromErrorString(
1473-
"Resume request failed - process still running.");
1471+
"resume request failed - process already running");
14741472
}
14751473
Status error = PrivateResume();
14761474
if (!error.Success()) {
@@ -1483,10 +1481,10 @@ Status Process::Resume() {
14831481
Status Process::ResumeSynchronous(Stream *stream) {
14841482
Log *log(GetLog(LLDBLog::State | LLDBLog::Process));
14851483
LLDB_LOGF(log, "Process::ResumeSynchronous -- locking run lock");
1486-
if (!m_public_run_lock.TrySetRunning()) {
1487-
LLDB_LOGF(log, "Process::Resume: -- TrySetRunning failed, not resuming.");
1484+
if (!m_public_run_lock.SetRunning()) {
1485+
LLDB_LOGF(log, "Process::Resume: -- SetRunning failed, not resuming.");
14881486
return Status::FromErrorString(
1489-
"Resume request failed - process still running.");
1487+
"resume request failed: process already running");
14901488
}
14911489

14921490
ListenerSP listener_sp(
@@ -2818,13 +2816,8 @@ Status Process::LaunchPrivate(ProcessLaunchInfo &launch_info, StateType &state,
28182816
SetPublicState(eStateLaunching, restarted);
28192817
m_should_detach = false;
28202818

2821-
if (m_public_run_lock.TrySetRunning()) {
2822-
// Now launch using these arguments.
2823-
error = DoLaunch(exe_module, launch_info);
2824-
} else {
2825-
// This shouldn't happen
2826-
error = Status::FromErrorString("failed to acquire process run lock");
2827-
}
2819+
m_public_run_lock.SetRunning();
2820+
error = DoLaunch(exe_module, launch_info);
28282821

28292822
if (error.Fail()) {
28302823
if (GetID() != LLDB_INVALID_PROCESS_ID) {
@@ -3089,17 +3082,12 @@ Status Process::Attach(ProcessAttachInfo &attach_info) {
30893082
if (wait_for_launch) {
30903083
error = WillAttachToProcessWithName(process_name, wait_for_launch);
30913084
if (error.Success()) {
3092-
if (m_public_run_lock.TrySetRunning()) {
3093-
m_should_detach = true;
3094-
const bool restarted = false;
3095-
SetPublicState(eStateAttaching, restarted);
3096-
// Now attach using these arguments.
3097-
error = DoAttachToProcessWithName(process_name, attach_info);
3098-
} else {
3099-
// This shouldn't happen
3100-
error =
3101-
Status::FromErrorString("failed to acquire process run lock");
3102-
}
3085+
m_public_run_lock.SetRunning();
3086+
m_should_detach = true;
3087+
const bool restarted = false;
3088+
SetPublicState(eStateAttaching, restarted);
3089+
// Now attach using these arguments.
3090+
error = DoAttachToProcessWithName(process_name, attach_info);
31033091

31043092
if (error.Fail()) {
31053093
if (GetID() != LLDB_INVALID_PROCESS_ID) {
@@ -3160,17 +3148,13 @@ Status Process::Attach(ProcessAttachInfo &attach_info) {
31603148
if (attach_pid != LLDB_INVALID_PROCESS_ID) {
31613149
error = WillAttachToProcessWithID(attach_pid);
31623150
if (error.Success()) {
3151+
m_public_run_lock.SetRunning();
31633152

3164-
if (m_public_run_lock.TrySetRunning()) {
3165-
// Now attach using these arguments.
3166-
m_should_detach = true;
3167-
const bool restarted = false;
3168-
SetPublicState(eStateAttaching, restarted);
3169-
error = DoAttachToProcessWithID(attach_pid, attach_info);
3170-
} else {
3171-
// This shouldn't happen
3172-
error = Status::FromErrorString("failed to acquire process run lock");
3173-
}
3153+
// Now attach using these arguments.
3154+
m_should_detach = true;
3155+
const bool restarted = false;
3156+
SetPublicState(eStateAttaching, restarted);
3157+
error = DoAttachToProcessWithID(attach_pid, attach_info);
31743158

31753159
if (error.Success()) {
31763160
SetNextEventAction(new Process::AttachCompletionHandler(
@@ -5951,10 +5935,9 @@ void Process::ClearPreResumeAction(PreResumeActionCallback callback, void *baton
59515935
}
59525936

59535937
ProcessRunLock &Process::GetRunLock() {
5954-
if (m_private_state_thread.EqualsThread(Host::GetCurrentThread()))
5938+
if (Process::CurrentThreadIsPrivateStateThread())
59555939
return m_private_run_lock;
5956-
else
5957-
return m_public_run_lock;
5940+
return m_public_run_lock;
59585941
}
59595942

59605943
bool Process::CurrentThreadIsPrivateStateThread()

0 commit comments

Comments
 (0)