<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/131242>131242</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
[lldb-dap] Race condition in the event handler thread
</td>
</tr>
<tr>
<th>Labels</th>
<td>
lldb,
lldb-dap
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
JDevlieghere
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
JDevlieghere
</td>
</tr>
</table>
<pre>
I discovered that `TestDAP_breakpointEvents.py` (macOS only) was failing nondeterministically. I tracked the problem down to the event handler thread (`EventThreadFunction`) where the check that a breakpoint has the DAP label would sometimes return false, even though the breakpoint in question was set through DAP.
I confirmed it's a race condition with the following assert:
```
bool is_dap = bp.MatchesName(BreakpointBase::GetBreakpointLabel());
assert(is_dap == bp.MatchesName(BreakpointBase::GetBreakpointLabel()));
```
The problem is that the operation of creating a breakpoint and adding the label are not atomic. Both SB API operations are protected by the target API lock. Here's what's going on:
1. The main thread receives a request to create a breakpoint with `setBreakpoints`. This calls `SBTarget::BreakpointCreateByLocation` which acquires the target API lock, creates the breakpoint and releases it.
2. The event thread receives an `eBreakpointEventTypeLocationsResolved` event and prepares to send a `breakpoint` event, which involves checking if the breakpoint has the DAP label. This calls `SBBreakpoint::MatchesName` which acquires the target API lock, doesn't find the label, and releases it.
3. Meanwhile on the main thread, we're trying to add the label in `dap::Breakpoint::SetBreakpoint`. This calls `SBBreakpoint::AddName` which waits on the API lock that's currently held by the event thread checking if the label is set.
In other words, creating the breakpoint and adding the label are not atomic operations. Individually they're protected by the target API mutex, but that doesn't help us since they're separate calls.
I see two ways to solve this problem:
1. Add a mutex to the `DAP` instance to synchronize between the main thread and the events thread.
2. Expose the _target API mutex_ as part of the SB API. It's a recursive mutex so there's no risk to locking it before calling SB APIs that are protected by it. I would want this to be an RAII object so I would not expose it through SWIG.
I'm leaning towards the second options because I think the use care here matches the idea behind the API lock.
</pre>
<img width="1" height="1" alt="" src="http://email.email.llvm.org/o/eJysVt1uGzcTfRrqZhBhRf1YutDFKorz6UPSGrGBXhrc5UjLmktuOFwp6tMXQ-rPdlq0QAEDhrjkzDkz5wypiMzOIS7FdCWk_P8a99bgrsGAQkoxXQ9UHxsflrdfBpXXx-UGtKHa7zGghtioCGJWPCHFdfnwXAVUL503Ln7ao4s07I5iVoCQ81bVvz6Cd_Yo5AIOimCrjDVuB847jRFDa5yhaGpl7XEIG4hB1S8pB0IXfGWxBe0PDqJPa8gZoFFOWwwQm4BKcyYxK1Lyp7Ry37s6Gu_ErEiJmUg6XjdYv2QCCq64oVGUvq_LB7CqQgsH31sN5FuMpkWCgLEPDrbKEgr5MQGB2Ph-16STN8GMg-89EgNInAkjI01b1-XDEERRiqLcQO3d1oQWNZgo5B2BgqBq5HVt8nETc_itt9YfuHKKCEMU4zJHYYr5rygr7y0YetaqAzFeQ9UNv6pYN0i_qBaFnK8uIFeKkGOMy88Yr8tfmDuXUy74b7wSRXlKKOfXyP9J8HP8WwaiKJ9uOm8o94or4DsMKhXFb6EOqGKqxm3hldOgtOZ1PpEbqQKC8xFU9K2ph7DysYHHFZQPm2tMStu64CPWETVUxxQhqrDDmLZaX78M4X_JK3cEh0bllu08p_Pu0pDREJhCq4w76zNgjWaPqb-YpMFyThzwNYPUbzEr6LZuJGYFBzUE7BPiDY-rp4Qtl_m692MKujp-8bU6OQAOjakbUPX33gSknxFjQWc49FbMXNOAFhUhgYlJvDJTzF58x9ExPly9HgpPxw7PmOgbkrd71AwuB-EsXcBOJYAeCLmVHOgK5bKb0WZOxu05EGVfcyPM9i2Bd9Z-X8or1lzOW13_4_ppj-SEvIuwNU5fBcjfflbE8RC-onKHxlgE79KBG9Ekkqw1nlzhmDTtWd030jap1Fp1b1WQfz_eiuinGnp7otT6NemDMpHO6M5skyeT-Os-BHTRHqFBe3HNK1287cwJeZqKw9MgdOBjgwEOPmi6aPFs439n8BtPD2HjtNkb3fPtwieOuZ5_5_O2j_iDMVR9zMPn2tgGbQc9ARlX4008YuGyl1Npr_OdECEePBzUMauaxQqRm3CacLdTo9Qs-ZT_fNuJWbEuH7gdxlFUKasHOrq6Cd6ZPxAqjAfEd-pJlbr0gk6rZ_N--tF5yhfi81vqz6AIOhUij1nekUflEDaXKwrrPpDZ4wkrJaynueg8BEMvDJOlkhofocKtD7k8vJJDnmb7u8HL_tic7t-DSkoyqXwV8nD5Vm424KvfsY6c-ryTFYCZl7let4-_bT5f-iHkXQsWlctmOqigs5sJ-cYF3-WroMJa9YT8GmmMe0lb-HfNUNNTos0DIn0xGhVU2JxNf70sBno51ovxQg1wObqbjBaj0WQxHTTLRVFM5mo6n2k5nkt5N5tVUhWj2VTNtmo6UQOzlIWcFuPRpChG89F0uJhM1HxUFXJb67GezMWkwFYZO7R23w592A0MUY_L0XgkJ3KQjEGnd561uuL3nfx4-vGBJ0Z-8IUlB_hQ9TsSk8IainQNGU206bF4OTRdw7fXDxTj_vJZNuiDXTYxdsQql_dC3u9MbPpqWPtWyHvOc_r3oQueGyrkfeJBQt6fqOyX8s8AAAD__1rEpTo">