Skip to content

Commit b1416c5

Browse files
committed
[lldb] Remove ProcessRunLock::TrySetRunning
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.
1 parent eb68b91 commit b1416c5

File tree

4 files changed

+35
-65
lines changed

4 files changed

+35
-65
lines changed

lldb/include/lldb/Host/ProcessRunLock.h

Lines changed: 6 additions & 1 deletion
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 true if the process was running.
3235
bool SetRunning();
33-
bool TrySetRunning();
36+
37+
/// Set the process to stopped. Returns true if the process was stopped.
38+
/// Returns false if the process was running.
3439
bool SetStopped();
3540

3641
class ProcessRunLocker {

lldb/source/Host/common/ProcessRunLock.cpp

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -37,21 +37,10 @@ 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() {
@@ -60,6 +49,7 @@ bool ProcessRunLock::SetStopped() {
6049
::pthread_rwlock_unlock(&m_rwlock);
6150
return true;
6251
}
63-
}
52+
53+
} // namespace lldb_private
6454

6555
#endif

lldb/source/Host/windows/ProcessRunLock.cpp

Lines changed: 4 additions & 12 deletions
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

Lines changed: 21 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -577,9 +577,7 @@ void Process::Finalize(bool destructing) {
577577
// contain events that have ProcessSP values in them which can keep this
578578
// process around forever. These events need to be cleared out.
579579
m_private_state_listener_sp->Clear();
580-
m_public_run_lock.TrySetRunning(); // This will do nothing if already locked
581580
m_public_run_lock.SetStopped();
582-
m_private_run_lock.TrySetRunning(); // This will do nothing if already locked
583581
m_private_run_lock.SetStopped();
584582
m_structured_data_plugin_map.clear();
585583
}
@@ -1325,9 +1323,9 @@ void Process::SetPublicState(StateType new_state, bool restarted) {
13251323
Status Process::Resume() {
13261324
Log *log(GetLog(LLDBLog::State | LLDBLog::Process));
13271325
LLDB_LOGF(log, "(plugin = %s) -- locking run lock", GetPluginName().data());
1328-
if (!m_public_run_lock.TrySetRunning()) {
1329-
LLDB_LOGF(log, "(plugin = %s) -- TrySetRunning failed, not resuming.",
1330-
GetPluginName().data());
1326+
if (!m_public_run_lock.SetRunning()) {
1327+
LLDB_LOGF(log, "(plugin = %s) -- SetRunning failed, not resuming.",
1328+
GetPluginName().data());
13311329
return Status::FromErrorString(
13321330
"Resume request failed - process still running.");
13331331
}
@@ -1342,8 +1340,8 @@ Status Process::Resume() {
13421340
Status Process::ResumeSynchronous(Stream *stream) {
13431341
Log *log(GetLog(LLDBLog::State | LLDBLog::Process));
13441342
LLDB_LOGF(log, "Process::ResumeSynchronous -- locking run lock");
1345-
if (!m_public_run_lock.TrySetRunning()) {
1346-
LLDB_LOGF(log, "Process::Resume: -- TrySetRunning failed, not resuming.");
1343+
if (!m_public_run_lock.SetRunning()) {
1344+
LLDB_LOGF(log, "Process::Resume: -- SetRunning failed, not resuming.");
13471345
return Status::FromErrorString(
13481346
"Resume request failed - process still running.");
13491347
}
@@ -2718,13 +2716,8 @@ Status Process::LaunchPrivate(ProcessLaunchInfo &launch_info, StateType &state,
27182716
SetPublicState(eStateLaunching, restarted);
27192717
m_should_detach = false;
27202718

2721-
if (m_public_run_lock.TrySetRunning()) {
2722-
// Now launch using these arguments.
2723-
error = DoLaunch(exe_module, launch_info);
2724-
} else {
2725-
// This shouldn't happen
2726-
error = Status::FromErrorString("failed to acquire process run lock");
2727-
}
2719+
m_public_run_lock.SetRunning();
2720+
error = DoLaunch(exe_module, launch_info);
27282721

27292722
if (error.Fail()) {
27302723
if (GetID() != LLDB_INVALID_PROCESS_ID) {
@@ -2989,17 +2982,12 @@ Status Process::Attach(ProcessAttachInfo &attach_info) {
29892982
if (wait_for_launch) {
29902983
error = WillAttachToProcessWithName(process_name, wait_for_launch);
29912984
if (error.Success()) {
2992-
if (m_public_run_lock.TrySetRunning()) {
2993-
m_should_detach = true;
2994-
const bool restarted = false;
2995-
SetPublicState(eStateAttaching, restarted);
2996-
// Now attach using these arguments.
2997-
error = DoAttachToProcessWithName(process_name, attach_info);
2998-
} else {
2999-
// This shouldn't happen
3000-
error =
3001-
Status::FromErrorString("failed to acquire process run lock");
3002-
}
2985+
m_public_run_lock.SetRunning();
2986+
m_should_detach = true;
2987+
const bool restarted = false;
2988+
SetPublicState(eStateAttaching, restarted);
2989+
// Now attach using these arguments.
2990+
error = DoAttachToProcessWithName(process_name, attach_info);
30032991

30042992
if (error.Fail()) {
30052993
if (GetID() != LLDB_INVALID_PROCESS_ID) {
@@ -3060,17 +3048,13 @@ Status Process::Attach(ProcessAttachInfo &attach_info) {
30603048
if (attach_pid != LLDB_INVALID_PROCESS_ID) {
30613049
error = WillAttachToProcessWithID(attach_pid);
30623050
if (error.Success()) {
3051+
m_public_run_lock.SetRunning();
30633052

3064-
if (m_public_run_lock.TrySetRunning()) {
3065-
// Now attach using these arguments.
3066-
m_should_detach = true;
3067-
const bool restarted = false;
3068-
SetPublicState(eStateAttaching, restarted);
3069-
error = DoAttachToProcessWithID(attach_pid, attach_info);
3070-
} else {
3071-
// This shouldn't happen
3072-
error = Status::FromErrorString("failed to acquire process run lock");
3073-
}
3053+
// Now attach using these arguments.
3054+
m_should_detach = true;
3055+
const bool restarted = false;
3056+
SetPublicState(eStateAttaching, restarted);
3057+
error = DoAttachToProcessWithID(attach_pid, attach_info);
30743058

30753059
if (error.Success()) {
30763060
SetNextEventAction(new Process::AttachCompletionHandler(
@@ -5882,10 +5866,9 @@ void Process::ClearPreResumeAction(PreResumeActionCallback callback, void *baton
58825866
}
58835867

58845868
ProcessRunLock &Process::GetRunLock() {
5885-
if (m_private_state_thread.EqualsThread(Host::GetCurrentThread()))
5869+
if (Process::CurrentThreadIsPrivateStateThread())
58865870
return m_private_run_lock;
5887-
else
5888-
return m_public_run_lock;
5871+
return m_public_run_lock;
58895872
}
58905873

58915874
bool Process::CurrentThreadIsPrivateStateThread()

0 commit comments

Comments
 (0)