Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix a race between lldb's packet timeout and the profile thread's usl…
…eep. The debugserver profile thread used to suspend itself between samples with a usleep. When you detach or kill, MachProcess::Clear would delay replying to the incoming packet until pthread_join of the profile thread returned. If you are unlucky or the suspend delay is long, it could take longer than the packet timeout for pthread_join to return. Then you would get an error about detach not succeeding from lldb - even though in fact the detach was successful... I replaced the usleep with PThreadEvents entity. Then we just call a timed WaitForEventBits, and when debugserver wants to stop the profile thread, it can set the event bit, and the sleep will exit immediately. Differential Revision: https://reviews.llvm.org/D75004
- Loading branch information
Showing
5 changed files
with
127 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
C_SOURCES := main.c | ||
CFLAGS_EXTRAS := -std=c99 | ||
|
||
include Makefile.rules |
76 changes: 76 additions & 0 deletions
76
lldb/test/API/macosx/profile_vrs_detach/TestDetachVrsProfile.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
""" | ||
debugserver used to block replying to the 'D' packet | ||
till it had joined the profiling thread. If the profiling interval | ||
was too long, that would mean it would take longer than the packet | ||
timeout to reply, and the detach would time out. Make sure that doesn't | ||
happen. | ||
""" | ||
|
||
|
||
|
||
import lldb | ||
import lldbsuite.test.lldbutil as lldbutil | ||
from lldbsuite.test.lldbtest import * | ||
from lldbsuite.test.decorators import * | ||
import os | ||
import signal | ||
|
||
class TestDetachVrsProfile(TestBase): | ||
|
||
mydir = TestBase.compute_mydir(__file__) | ||
|
||
NO_DEBUG_INFO_TESTCASE = True | ||
|
||
@skipUnlessDarwin | ||
@skipIfOutOfTreeDebugserver | ||
def test_profile_and_detach(self): | ||
"""There can be many tests in a test case - describe this test here.""" | ||
self.build() | ||
self.main_source_file = lldb.SBFileSpec("main.c") | ||
self.do_profile_and_detach() | ||
|
||
def do_profile_and_detach(self): | ||
(target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self, | ||
"Set a breakpoint here", self.main_source_file) | ||
|
||
interp = self.dbg.GetCommandInterpreter() | ||
result = lldb.SBCommandReturnObject() | ||
|
||
# First make sure we are getting async data. Set a short interval, continue a bit and check: | ||
interp.HandleCommand("process plugin packet send 'QSetEnableAsyncProfiling;enable:1;interval_usec:500000;scan_type=0x5;'", result) | ||
self.assertTrue(result.Succeeded(), "process packet send failed: %s"%(result.GetError())) | ||
|
||
# Run a bit to give us a change to collect profile data: | ||
bkpt.SetIgnoreCount(1) | ||
threads = lldbutil.continue_to_breakpoint(process, bkpt) | ||
self.assertEqual(len(threads), 1, "Hit our breakpoint again.") | ||
str = process.GetAsyncProfileData(1000) | ||
self.assertTrue(len(str) > 0, "Got some profile data") | ||
|
||
# Now make the profiling interval very long and try to detach. | ||
interp.HandleCommand("process plugin packet send 'QSetEnableAsyncProfiling;enable:1;interval_usec:10000000;scan_type=0x5;'", result) | ||
self.assertTrue(result.Succeeded(), "process packet send failed: %s"%(result.GetError())) | ||
self.dbg.SetAsync(True) | ||
listener = self.dbg.GetListener() | ||
|
||
# We don't want to hit our breakpoint anymore. | ||
bkpt.SetEnabled(False) | ||
|
||
# Record our process pid so we can kill it since we are going to detach... | ||
self.pid = process.GetProcessID() | ||
def cleanup(): | ||
self.dbg.SetAsync(False) | ||
os.kill(self.pid, signal.SIGKILL) | ||
self.addTearDownHook(cleanup) | ||
|
||
process.Continue() | ||
|
||
event = lldb.SBEvent() | ||
success = listener.WaitForEventForBroadcaster(0, process.GetBroadcaster(), event) | ||
self.assertTrue(success, "Got an event which should be running.") | ||
event_state = process.GetStateFromEvent(event) | ||
self.assertEqual(event_state, lldb.eStateRunning, "Got the running event") | ||
|
||
# Now detach: | ||
error = process.Detach() | ||
self.assertTrue(error.Success(), "Detached successfully") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
#include <stdio.h> | ||
|
||
int | ||
main() | ||
{ | ||
while (1) { | ||
sleep(1); // Set a breakpoint here | ||
printf("I slept\n"); | ||
} | ||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters