Why does Platform::DebugProcess always launch and then attach?

In particular this code:

error = LaunchProcess (launch_info);
if (error.Success())
{
if (log)
log->Printf (“Platform::%s LaunchProcess() call succeeded (pid=%” PRIu64 “)”, FUNCTION, launch_info.GetProcessID ());
if (launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID)
{
ProcessAttachInfo attach_info (launch_info);
process_sp = Attach (attach_info, debugger, target, error);

For Windows if you want to launch a program under the debugger the method you use launch to launch the process also does the attach at the same time. Until recently, PlatformWindows::CanDebugProcess() had been returning false, so it was falling back to calling Process::DoLaunch(), which has been working fine.

I’m adding support for attaching to processes though, and this requires changing that function to return true. So now both launches and attaches go through this path of launching first, and then attaching, which causes the launch codepath to break.

What is the correct way to handle this? Could I add a method to Platform called SupportsAtomicLaunchAndAttach() that if true will just call Process::DoLaunch() directly, and if false will continue down the existing codepath?

Alternatively I could just override Platform::DebugProcess() in PlatformWindows. It says in the header that you shouldn’t need to do that, but maybe that’s still a cleaner solution than adding this other function.

The theory is to require platforms to implement the minimum number of functions.

If you implement launch and attach, then you shouldn't need a third function to debug your process.

This all hinges on your ability to stop your program at the entry point when the eLaunchFlagDebug launch flag is set. If you can do this, then you should be able to use launch followed by attach. If you can't do this, you will need to override the PlatformWindows::DebugProcess(...).

Greg

I’ve overridden DebugProcess but for some reason LLDB thinks my process has exited even when it hasn’t. Can you tell from looking at this log what might be going wrong?

1431622791.100000000 Processing command: process attach -p 9664
1431622791.100000000 HandleCommand, cmd_obj : ‘process attach’
1431622791.100000000 HandleCommand, (revised) command_string: ‘process attach -p 9664’
1431622791.100000000 HandleCommand, wants_raw_input:‘False’
1431622791.101000000 HandleCommand, command line after removing command name(s): ‘-p 9664’
1431622791.101000000 039FD150 Listener::Listener(‘lldb.Target.Attach.attach.hijack’)
1431622791.102000000 039FD5D8 Broadcaster::Broadcaster(“lldb.process”)
1431622791.102000000 039FD654 Broadcaster::Broadcaster(“lldb.process.internal_state_broadcaster”)
1431622791.102000000 039FD6A0 Broadcaster::Broadcaster(“lldb.process.internal_state_control_broadcaster”)
1431622791.103000000 039FD6EC Listener::Listener(‘lldb.process.internal_state_listener’)
1431622791.103000000 039FD8AC Broadcaster::Broadcaster(“process.stdio”)
1431622791.103000000 039FD8AC Communication::Communication (name = process.stdio)
1431622791.103000000 032B82C0 Listener::StartListeningForEvents (broadcaster = 039FD5D8, mask = 0x0000000d) acquired_mask = 0x0000000d for lldb.Debugger
1431622791.103000000 039FD5C8 Process::Process()
1431622791.103000000 032B82C0 Listener::StartListeningForEvents (broadcaster = 039FD5D8, mask = 0x0000001f) acquired_mask = 0x0000001f for lldb.Debugger
1431622791.103000000 039FD6EC Listener::StartListeningForEvents (broadcaster = 039FD654, mask = 0x00000003) acquired_mask = 0x00000003 for lldb.process.internal_state_listener
1431622791.103000000 039FD6EC Listener::StartListeningForEvents (broadcaster = 039FD6A0, mask = 0x00000007) acquired_mask = 0x00000007 for lldb.process.internal_state_listener
1431622791.104000000 Process::SetPublicState (state = attaching, restarted = 0)
1431622791.104000000 Process::SetPrivateState (attaching)
1431622791.104000000 039FD654 Broadcaster(“lldb.process.internal_state_broadcaster”)::BroadcastEvent (event_sp = {03A03220 Event: broadcaster = 039FD654 (lldb.process.internal_state_broadcaster), type = 0x00000001, data = { process = 039FD5C8 (pid = 0), state = attaching}}, unique =0) hijack = 00000000
1431622791.104000000 039FD6EC Listener(‘lldb.process.internal_state_listener’)::AddEvent (event_sp = {03A03220})
1431622791.104000000 DebuggerThread::DebugAttach attaching to ‘9664’
1431622791.104000000 WaitForDebuggerConnection Waiting for initial stop.
1431622791.105000000 thread created
1431622791.105000000 DebuggerThread preparing to attach to process ‘9664’ on background thread.
1431622791.105000000 Entering WaitForDebugEvent loop
1431622791.105000000 HandleCreateProcessEvent process 9664 spawned
1431622791.106000000 Debugger established connected to process 9664. Image base = 0x1240000
1431622791.153000000 035EA020 Broadcaster(“lldb.target”)::BroadcastEvent (event_sp = {035E1AC8 Event: broadcaster = 035EA020 (lldb.target), type = 0x00000002 (modules-loaded), data = {}}, unique =0) hijack = 00000000
1431622791.168000000 035EA020 Broadcaster(“lldb.target”)::BroadcastEvent (event_sp = {04453CF8 Event: broadcaster = 035EA020 (lldb.target), type = 0x00000002 (modules-loaded), data = {}}, unique =0) hijack = 00000000
1431622791.169000000 035EA020 Broadcaster(“lldb.target”)::BroadcastEvent (event_sp = {04305458 Event: broadcaster = 035EA020 (lldb.target), type = 0x00000002 (modules-loaded), data = {}}, unique =0) hijack = 00000000
1431622791.180000000 035EA020 Broadcaster(“lldb.target”)::BroadcastEvent (event_sp = {035FE9E0 Event: broadcaster = 035EA020 (lldb.target), type = 0x00000002 (modules-loaded), data = {}}, unique =0) hijack = 00000000
1431622791.181000000 035EA020 Broadcaster(“lldb.target”)::BroadcastEvent (event_sp = {04308570 Event: broadcaster = 035EA020 (lldb.target), type = 0x00000002 (modules-loaded), data = {}}, unique =0) hijack = 00000000
1431622791.193000000 035EA020 Broadcaster(“lldb.target”)::BroadcastEvent (event_sp = {03605E60 Event: broadcaster = 035EA020 (lldb.target), type = 0x00000002 (modules-loaded), data = {}}, unique =0) hijack = 00000000
1431622791.194000000 035EA020 Broadcaster(“lldb.target”)::BroadcastEvent (event_sp = {044D69E8 Event: broadcaster = 035EA020 (lldb.target), type = 0x00000002 (modules-loaded), data = {}}, unique =0) hijack = 00000000
1431622791.194000000 HandleCreateThreadEvent Thread 9664 spawned in process 20100446945280
1431622791.194000000 HandleExceptionEvent encountered first chance exception 0x80000003 (breakpoint) on thread 4680
1431622791.194000000 Process::SetPrivateState (stopped)
1431622791.194000000 Process::SetPrivateState (stopped) stop_id = 1
1431622791.194000000 DoAttachToProcessWithID successfully attached to process with pid=9664
1431622791.194000000 039FD654 Broadcaster(“lldb.process.internal_state_broadcaster”)::BroadcastEvent (event_sp = {032C56C8 Event: broadcaster = 039FD654 (lldb.process.internal_state_broadcaster), type = 0x00000001, data = { process = 039FD5C8 (pid = 0), state = stopped}}, unique =0) hijack = 00000000
1431622791.194000000 Process::AttachCompletionHandler::lldb_private::Process::AttachCompletionHandler::AttachCompletionHandler process=039FD5C8, exec_count=0
1431622791.194000000 039FD6EC Listener(‘lldb.process.internal_state_listener’)::AddEvent (event_sp = {032C56C8})
1431622791.194000000 Process::lldb_private::Process::StartPrivateStateThread() starting private state thread
1431622791.194000000 DebuggerThread::HandleExceptionEvent waiting for ExceptionPred != BreakInDebugger
1431622791.194000000 Process::lldb_private::Process::ControlPrivateStateThread (signal = 4)
1431622791.195000000 039FD6A0 Broadcaster(“lldb.process.internal_state_control_broadcaster”)::BroadcastEvent (event_sp = {032C1A58 Event: broadcaster = 039FD6A0 (lldb.process.internal_state_control_broadcaster), type = 0x00000004 (control-resume), data = }, unique =0) hijack = 00000000
1431622791.195000000 039FD6EC Listener(‘lldb.process.internal_state_listener’)::AddEvent (event_sp = {032C1A58})
1431622791.195000000 thread created
1431622791.195000000 Process::lldb_private::Process::RunPrivateStateThread (arg = 039FD5C8, pid = 9664) thread starting…
1431622791.195000000 Sending control event of type: 4.
1431622791.195000000 Process::lldb_private::Process::WaitForEventsPrivate (timeout = 00000000, event_sp)…
1431622791.195000000 039FD6EC Listener::WaitForEventsInternal (timeout = { 00000000 }) for lldb.process.internal_state_listener
1431622791.195000000 039FD6EC ‘lldb.process.internal_state_listener’ Listener::FindNextEventInternal(broadcaster=039FD6A0, broadcaster_names=00000000[0], event_type_mask=0x00000000, remove=1) event 032C1A58
1431622791.195000000 Process::lldb_private::Process::RunPrivateStateThread (arg = 039FD5C8, pid = 9664) got a control event: 4
1431622791.195000000 Process::lldb_private::Process::WaitForEventsPrivate (timeout = 00000000, event_sp)…
1431622791.195000000 039FD6EC Listener::WaitForEventsInternal (timeout = { 00000000 }) for lldb.process.internal_state_listener
1431622791.195000000 Process::lldb_private::Process::WaitForProcessToStop (timeout = 00000000)
1431622791.195000000 039FD6EC ‘lldb.process.internal_state_listener’ Listener::FindNextEventInternal(broadcaster=00000000, broadcaster_names=00000000[0], event_type_mask=0x00000000, remove=1) event 03A03220
1431622791.195000000 Process::lldb_private::Process::WaitForStateChangedEvents (timeout = 00000000, event_sp)…
1431622791.195000000 039FD150 Listener::WaitForEventsInternal (timeout = { 00000000 }) for lldb.Target.Attach.attach.hijack
1431622791.195000000 Process::AttachCompletionHandler::lldb_private::Process::AttachCompletionHandler::PerformAction called with state attaching (3)
1431622791.195000000 Ran next event action, result was 2.
1431622791.195000000 Process::SetExitStatus (status=0 (0x00000000), description=“No valid Process”)
1431622791.195000000 Process::SetPrivateState (exited)
1431622791.195000000 Process::SetPrivateState (exited) stop_id = 2

The key seems to be this AttachCompletionHandler::PerformHandler being called with state attaching. For some reason LLDB is turning that into “the process is exiting”.

It’s possible I’m misunderstanding the purpose of this AttachCompletionHandler, but on the surface it seems like “Attaching” is the expected state for the program to be in when this happens.

With Launch, the way it works is that I return from DoLaunch() with my private state set to eStateStopped (because the program is stopped at the initial breakpoint) and LLDB calls DoResume() on me eventually. With attach, I’m doing the same thing – returning from DoAttachToProcessWithID when my private state is set to eStateStopped and public state set to eStateAttaching (m_continue_once_attached = false, so it actually is stopped when I return from DoAttach).

Do I have the states mixed up with regards to what LLDB is expecting?

Set a breakpoint on Process::SetExitStatus() and see who is calling this. This is what is causing the process to think it has exited. As soon as this is called, your process is exited and it won't recover.