Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [cdt-dev] Setting correct state for suspend/resume icons in debugger

Marc
I've been sidetracked working on other things this week and am just getting back to this this week.

I think my case can be considered almost identical to the manual remote session in CDT. 

My agent is supposed to work like gdbserver, except I have to get the correct port number dynamically, where my agent writes a file containing the port number where I know how to find it. 

I also am treating this as if this is a remote session even though it's running on the local machine. I think all that means is that the hostname is localhost instead of some other hostname. 

I modified my code so that it starts my agent early in debugger startup then extended DebugNewProcessSequence_7_2 to override stepRemoteConnection so that I can get the port number I need to issue the 'target remote' command.

I also looked at the .launch file written for a manual remote launch configuration and tried to match the CDT attributes set in that launch configuration in my UI class that updates my launch configuration.

I ended up doing the following


                configuration
                .setAttribute(
                        ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_START_MODE,
                        IGDBLaunchConfigurationConstants.DEBUGGER_MODE_REMOTE);
                configuration.setAttribute("org.eclipse.debug.core.REMOTE_TCP",
                        "Local");
                configuration
                        .setAttribute(
                                IGDBLaunchConfigurationConstants.ATTR_HOST,
                                "localhost");
                configuration.setAttribute(
                        IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_REVERSE,
                        false);
                configuration
                        .setAttribute(
                                IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_TRACEPOINT_MODE,
                                IGDBLaunchConfigurationConstants.DEBUGGER_TRACEPOINT_NORMAL_ONLY);
                configuration.setAttribute(
                        ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_ID,
                        "gdbserver");
                configuration
                .setAttribute(
                        IRemoteConnectionConfigurationConstants.ATTR_SKIP_DOWNLOAD_TO_TARGET,
                        true);
                configuration
                        .setAttribute(
                                IGDBLaunchConfigurationConstants.ATTR_DEBUGGER_NON_STOP,
                                false);
                configuration.setAttribute(
                        IGDBLaunchConfigurationConstants.ATTR_REMOTE_TCP, true);

If I set a breakpoint in my target application taht I know my application will reach, then once the breakpoint is hit, the debugger seems to behave normally.

If I look at the gdb traces console, I can see that at stepRunProgram, the application program is suspended. I see the -exec-continue issued by gdb and see the state change to running.

If I remove the breakpoint, start my application, and attach to it, then only the 'continue' and 'stop' icons are enabled. The 'suspend' and 'step' icons are disabled. So I cannot suspend the application. If I press  the 'stop' icon, the 'continue' and 'stop' icons are now also disabled and the program does not terminate. I can see an '-exec-interrupt' sent but it does nothing.

If I start the application, attach to it and manually send a 'kill -INT' to it, it does suspend, but the stack is incorrect in that there is no function names or line numbers. If I try to single step at that point, then I see a message in the gdb traces console from gdb that it cannot determine the bounds of the function and the step fails. Searching for this message got me to web pages that tell me that gdb has not loaded symbol information yet.

I'm kind of surprised that the debugger is still sending -exec-interrupt to gdb even after I set the org.eclipse.cdt.dsf.gdb.NON_STOP attribute to false. Looking at the gdb traces console for CDT remote gdbserver sessions I see that the debugger is sending SIGINT to gdb.

I know if -exec-continue is sent in all-stop mode, nothing happens until gdb has a reason to issue a console read. Could my problems be that I'm still not setting up all-stop mode correctly?

Do you have any suggestions what I should look at to try to figure out the problems?

Thanks for helping with this.

Dave
---- Marc Khouzam <marc.khouzam@xxxxxxxxxxxx> wrote: 
> Before stepRunProgram, the debugger is not in a running state normally.  Maybe that is the difference in your case?

To interrupt it maybe using GDBBackend.interruptAndWait() or interrupt() or interruptInferiorAndWait().  Look at how they are implemented, and you may need to modify them because they behave differently based on 
if (getSessionType() == SessionType.REMOTE)
which is not the case for you, but maybe it should look like it is.

________________________________________
From: David Wootton [drwootton@xxxxxxxxxx]
Sent: January 30, 2015 7:05 AM
To: Marc Khouzam
Subject: Re: [cdt-dev] Setting correct state for suspend/resume icons in   debugger

Marc
Is there any way to force the debugger/ui into 'suspended' state using public apis, maybe as a step just before stepRunProgram? It seems that at least for my plugins, there aren't any variations of debugger configurations, and that I should be able to reliably assert that the application is suspended at that time, and so just 'sync up' the ui with application state?

I think other than the problem I have with toolbar icons and menus, What I have works.

Dave

On January 29, 2015, at 16:22, Marc Khouzam <marc.khouzam@xxxxxxxxxxxx> wrote:

HI Dave,

this looks like a pretty complicated situation :)

You don't use gdbserver, but you use an agent to which gdb must connect using target remote.  So, effectively, this is a remote session.  The tricky thing may be that if your agent does not behave as gdbserver, then CDT may not be ready for it.

I don't want to point you to a direction that will make you waste time, but the way you describe your system is sounds like CDT's Automatic Remote debugging.  In that situation, CDT first starts gdbserver and the process that will be debugged, then connects to gdbserver and does what it needs to get the session properly setup.

In your case, you start your agent (instead of gdbserver) and need GDB to connect to it and get everything setup.  Sounds very similar to me.  Couldn't you extend CDT's Manual Remote debugging session (that is the one that expects gdbserver/agent to be started somehow) and just add a step at the start to start your agent?
________________________________________
From: drwootton@xxxxxxxxxx [drwootton@xxxxxxxxxx]
Sent: January 29, 2015 8:06 AM
To: Marc Khouzam
Subject: RE: [cdt-dev] Setting correct state for suspend/resume icons in debugger

Marc
In my model, everything runs on the local machine, no remote execution. Only one application process is supported, and that process may be multi-threaded. I support both launch, which seems to be working correctly, and attach to a running process, which is working other than properly suspending the application when the debugger connects. There is no gdbserver process.

The code flow thru my plugins is pretty much the same for both the launch and attach cases.

I extended the FinalLaunchSequence_7_7 class two add two new steps to start my agent and connect to it.

In the first step, I launch the agent process. The agent process either loads the executable in launch mode or attaches, I think via ptrace, in attach mode. In attach mode, the application seems to be suspended at attach, as shown by previous gdb trace logs. Then the agent process opens a local port and waits for gdb to connect to it.

In the second step I find the port that I need to connect gdb to and issue a 'gdb target remote :nnnnn' command to connect to that agent.

The rest of the steps in FinalLaunchSequence_7_7 are unmodified, so gdb also continues to load a second copy of the executable is if it was running in launch mode. I'm not sure what gdb does with this second copy, since once the target remote command is issued, my understanding is that my agent picks off the commands it handles and gives the rest back to gdb so it can manipulate the connected application process. It may be gdb only uses the loaded copy to get symbol and line information, not sure. No time, as shown by ps, accumulates for the loaded process when I resume the connected process in gdb.

I think the only remaining problem to solve is how to get the target application process suspended after the stepRunJob step resumes it and to get the CDT debugger to properly reflect the suspended state, where the toolbar icons and menu choices are in their proper states.

I had made an attempt to make this work by sending the target process a SIGINT to suspend it. I was able to suspend the process as long as I didn't trap SIGINT by something like 'signal(SIGINT, SIG_IGN)'. Since this approach didn't work when SIGINT was trapped, I'm trying to get my current approach to work.

Dave
---- Marc Khouzam <marc.khouzam@xxxxxxxxxxxx> wrote:
> You are right, in -exec-continue returns ^running instead of ^done. And then there is a *running event.

Now, let me try to understand what you are really trying to achieve.  CDT has a remote-attach launch that maybe is what you need?  This launch connects gdb with gdbserver and then allows the user to attach to a running process.

Look for "Remote Attach Launch" in this page
https://wiki.eclipse.org/CDT/User/FAQ#How_do_I_debug_a_remote_application.3F

You can then explain what is different in your situation and we'll try to figure out how to make it work.
________________________________________
From: drwootton@xxxxxxxxxx [drwootton@xxxxxxxxxx]
Sent: January 28, 2015 11:26 AM
To: Marc Khouzam
Subject: RE: [cdt-dev] Setting correct state for suspend/resume icons in debugger

Marc
With my changes, I'm seeing the '*running' event resulting from the -exec-continue issued by stepRunningProgram, but I am not seeing any '^done' response for the -exec-continue command.

That's why I'm thinking that the step processing in the plugin is not waiting until the current step (stepRunProgram) completes before running any subsequent steps including the step I issued to try to suspend the program again. So when my new step calls suspend(), it's doing this before gdb and the CDT plugins have gotten into sync with the running status from the -exec-continue command, the plugin thinks the program is still suspended, and so the exception is raised because I'm trying to suspend a program the plugins still think is suspended.

Based on this, I think I need a way to block the step processing at my step until I know that the '*running' notification has been processed by the plugins.

I tried to do this by coding a loop in my new step, looping until runControl.isSuspended() returns true, but that just hung the debugger and I never see a '^done' notification for the -exec-continue.

Basically, what I'm trying to do with my plugins is to attach to a running process and then suspend it as it it had been interrupted by the user so he can look around, figure out where the application is, and set breakpoints before continuing. I'm also trying to maintain existing CDT debugger behavior as much as possible with no side effects other that anything the user does with my added debugger commands.

My approach was to let the stepRunProgram step resume program execution since there is some processing in stepRunProgram that needs to be preserved, and then after the program was in running state suspend it again so the user can set breakpoints, etc.

Is this possible to make this work?

Also, the fragment of the gdb traces log from just before the -exec-continue command are below

Dave


327,427 (gdb)
327,427 37^done,depth="1"
327,427 (gdb)
327,428 38-inferior-tty-set --thread-group i1 /dev/pts/35
327,430 38^done
327,430 (gdb)
327,438 39-exec-continue --thread-group i1
327,554 40-thread-info 1
327,635 39^running
327,636 *running,thread-id="all"
327,636 (gdb)
327,645 41-stack-info-depth --thread 1 2
327,647 42-gdb-exit
329,650 =thread-group-exited,id="i1"
329,651 &"Remote connection closed\n"
329,651 ~"target.c:2813: internal-error: could not find a target to follow mourn inferior\nA problem\
 internal to GDB has been detected,\nfurther debugging may prove unreliable.\nQuit this debugging se\
ssion? "
329,651 ~"(y or n) [answered Y; input not from terminal]\n"
329,652 ~"target.c:2813: internal-error: could not find a target to follow mourn inferior\nA problem\
 internal to GDB has been detected,\nfurther debugging may prove unreliable.\nCreate a core file of \
GDB? "
329,652 ~"(y or n) [answered Y; input not from terminal]\n"
329,664 43-stack-info-depth --thread 1 11



---- Marc Khouzam <marc.khouzam@xxxxxxxxxxxx> wrote:
> Yes, a very important thing to understand about all the runControl commands (-exec-interrupt, -exec-continue,-exec-next) is that when GDB returns ^done it only means the command was started; it does not mean the command had completed.  You need to get *stopped events for the target to be suspended again.
________________________________________
From: drwootton@xxxxxxxxxx [drwootton@xxxxxxxxxx]
Sent: January 28, 2015 9:08 AM
To: Marc Khouzam
Subject: RE: [cdt-dev] Setting correct state for suspend/resume icons in debugger

Marc
I tried both of these suggestions and am still having problems, where I think the plugin code still sees gdb in a suspended state even though the -exec-continue command has been issued.

My first attempt was to run another step immediately after stepRunProgram to call runControl.suspend(). That failed with an exception with the first few lines

java.lang.IllegalStateException: RequestMonitor: Sequence "", result for executing step #9 = Status ERROR: org.eclipse.cdt.dsf.gdb code=10003 Given context: gdb[1].proc[].threadGroup[i1], is already suspended. null, done() method called more than once
        at org.eclipse.cdt.dsf.concurrent.RequestMonitor.done(RequestMonitor.java:285)
        at com.intel.drdebug.gdb.local.LocalStartOrRestartProcessSequence.stepInterruptProgram(LocalStartOrRestartProcessSequence.java:168)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)

This leads me to believe the plugins think the debugger/application is still suspended at that instant.

I tried calling IGDBBackend.interrupt() and that also failed. I stepped thru the code in the debugger and runControl was not null, so isTartgetAcceptingCommands() must be true, again leading me to believe the plugin still thought the debugger/application was suspended.

Then I moved the invocation of my step to just after stepContinue() to see if allowing some time to pass after issuing -exec-continue affected this and still failed.

Does the steps mechanism wait until the preceding step has completed before running the next step? Do I need to do something myself to wait until the -exec-continue command has been fully processed?

Dave
---- Marc Khouzam <marc.khouzam@xxxxxxxxxxxx> wrote:
> Woops.  The pattern is:

fBackend = getServicesTracker().getService(IGDBBackend.class);
IMIRunControl runControl = getServicesTracker().getService(IMIRunControl.class);
if (runControl != null && !runControl.isTargetAcceptingCommands()) {
        fBackend.interrupt();
}
________________________________________
From: Marc Khouzam
Sent: January 27, 2015 10:50 AM
To: drwootton@xxxxxxxxxx
Subject: RE: [cdt-dev] Setting correct state for suspend/resume icons in debugger

HI Dave,

-exec-interrupt does not work in all-stop mode with CDT.  The reason is that when GDB is running the program, it is not accepting any commands.  You can try that in the command-line in fact.  Once you press continue for your program, you cannot sent GDB any other command until you press ^C.

What you should do is use the IRunControl service and call IRunControl.suspend().  This will intelligently decide how to interrupt GDB, depending on if it is in all-stop or non-stop.

If, for some reason you cannot use that service, then you can fallback to calling IGDBBackend.interrupt*() .  The pattern we use sometimes is:

________________________________________
From: drwootton@xxxxxxxxxx [drwootton@xxxxxxxxxx]
Sent: January 27, 2015 8:45 AM
To: Marc Khouzam
Subject: RE: [cdt-dev] Setting correct state for suspend/resume icons in debugger

Marc
At this point all I need is all-stop mode.

There was no '--exec-continue' being issued to the debugger. The reason was that I was overriding StartOrRestartProcessSequence_7_0.stepRunProgram(), and in the case where I'm running my attach mode, I was not calling super.stepRunProgram() since when I wrote the code, thinking I didn't want to send an --exec-continue command, just an --exec-interrupt command because I incorrectly assumed the program was already running.

Now I changed the code to call super.stepRunProgram() to issue '--exec-continue' before issuing '--exec-interrupt'.

The gdb traces log shows a '*running' event, but the --exec-continue does not compete and the program keeps running. I then issued a 'kill -INT <pid>' for the target process from a command line. Then the process suspended and the --exec-interrupt command completed and the stack looked normal. This isn't what I wanted since I expected the --exec-interrupt command to suspend the program.

I changed my code so I no longer override stepRunProgram, and added a new step just after stepRunProgram to just issue the --exec-interrupt command with the same result.

The method I added is below, where 'context' is a copy of the containerDmc parameter from the class constructor

@Execute

    public void stepInterruptProgram(final RequestMonitor rm) {
        final String method = "stepInterruptProgram"; //$NON-NLS-1$
        Log.entry(className, method);
        if (attachMode) {
            ICommand<MIInfo> command = GDBCommandFactory.getInstance()
                    .createMIExecInterrupt(context);
            commandControl.queueCommand(command,
                    new ImmediateDataRequestMonitor<MIInfo>(rm));
        }
        rm.done();
        Log.exit(method, className)
    }

The gdb traces log is attached. I added a couple blank lines in the log at the point just before I issued the 'kill -INT' command

Dave
---- Marc Khouzam <marc.khouzam@xxxxxxxxxxxx> wrote:
> Hi Dave,

so you are using all-stop mode.  Maybe that is only what your target supports.  But that is ok, if that is what you need.

Now, when you connect to the remote you get a *stopped which is normal.  CDT normally should send the -exec-continue itself to get to the breakpoint at main.

Note that -exec-continue --all does not work in all-stop mode, so just -exec-continue should be fine.
________________________________________
From: drwootton@xxxxxxxxxx [drwootton@xxxxxxxxxx]
Sent: January 26, 2015 11:37 AM
To: Marc Khouzam
Subject: RE: [cdt-dev] Setting correct state for suspend/resume icons in debugger

Marc
There is no *stopped' event following the '-exec-interrupt' command. Looking backwards in the gdb traces, I see that that there was a '*stopped' event just after I issued a 'target remote' command. There is no subsequent '*running' event, so I think the application was already stopped at the point I issued the '-exec-interrupt

I tried issuing an '-exec-continue --all' after the 'target remote' command but then the debug session just hung shortly after the '-exec-continue' command, maybe because CDT was waiting for responses to following commands.

The debug traces console without the '--exec-continue --all' command is attached

Dave

---- Marc Khouzam <marc.khouzam@xxxxxxxxxxxx> wrote:
> >Marc
>I haven't done much more with this problem.
>
>If I look at the gdb trace console, I see the following log immediately befoe and after the -exec-interrupt command, so I think gdb has processed the command.

There should be a *stopped event in that output.  Or maybe it follows the part you included?  The *stopped event is sent by GDB to indicate that one or all threads have been suspended.  This is how CDT knows to show the stack frames and enable the resume button.

>The target process does get interrupted, since at that point I can modify the variable the code is looping on using the debugger and resume execution past the loop.

It looks like your GDB has interrupted the process but did not send the necessary *stopped event.

>The only things I'm seeing wrong are that the toolbar icons don't behave properly and the call stack doesn't look right at the time of the interrupt. Once I single step once, then the icons behave properly and the stack looks ok.

That makes sense because after a new step, there is a new *stopped event to indicate that the thread has suspended again.

>---
>370,049 (gdb)
>370,061 37-exec-interrupt --thread-group i1
>370,062 37^done
>370,062 (gdb)
>370,066 38info sources
>370,066 &"info sources\n"
>370,067 ~"Source files for which symbols have been read in:\n\n"
>370,074 ~"elf-init.c, /usr/lib64/gcc/x86_64-suse-linux/4.3/include/stddef.h, /nfs/mmdc/disks/tpi2/us\
>---
>
>I'm not sure where I should be looking for notification of the *stopped event. I do have an IDebugEventSetListener that I registered by calling DebugPlugin.getDefault().addDebugEventListener(), but that does not seem to see any debug events except for some 'create' and 'change' events even when I resume and execution hits a breakpoint. The only events I see are termination events when the program ends.

The above listener is for platform debug events and are usually not what you would look for using DSF.
As for the *stopped event, it is processes automatically by CDT so you don't need to worry about it.  But you need to make sure GDB does send it each time a thread is suspended.

>
>---
>Debug event:
>Source: org.eclipse.cdt.dsf.gdb.launching.GDBProcess@6cd0361a kind 16 detail 0
>Debug event:
>Source: org.eclipse.cdt.dsf.gdb.launching.GDBProcess@6cd0361a kind 4 detail 0
>Debug event:
>Source: org.eclipse.cdt.dsf.gdb.launching.InferiorRuntimeProcess@e820760 kind 16 detail 0
>Debug event:
>Source: org.eclipse.cdt.dsf.gdb.launching.InferiorRuntimeProcess@e820760 kind 4 detail 0
>Debug event:
>Source: org.eclipse.cdt.dsf.gdb.launching.InferiorRuntimeProcess@e820760 kind 16 detail 0
>---
>
>I'm not sure if the -exec-interrupt command is supposed to be used since I did find a comment in org.eclipse.cdt.debug.mi.core.CommandFactory that says -exec-interrupt is not supported, but don't know the context of the comment.

Since you use DSF-GDB, you should not be looking in o.e.cdt.debug.mi*, as this is the old CDI code.
We do support -exec-interrupt for non-stop mode, which you seem to be using.

One thing to make sure of is that the process is actually interrupted when you send -exec-interrupt.  We cannot know this from the few traces shown above.  Maybe the missing *stopped event after -exec-interrupt is that the process was already stopped?

>
>Thanks for looking at this.
>
>Dave
>---- Marc Khouzam <marc.khouzam@xxxxxxxxxxxx> wrote:
>> Hi David,
>>
>> I see you didn't get an answer yet.  People have been pretty busy with our upcoming release.
>>
>> Did you make any progress on your issue?  If not, let me ask if you are getting a *stopped event after the -exec-interrupt you send.  If you don't then CDT does not realize the program has been interrupted.
>>
>> Marc
>>
>> ________________________________________
>> From: cdt-dev-bounces@xxxxxxxxxxx [cdt-dev-bounces@xxxxxxxxxxx] on behalf of David Wootton [drwootton@xxxxxxxxxx]
>> Sent: January 13, 2015 11:51 AM
>> To: cdt-dev@eclipse org
>> Subject: [cdt-dev] Setting correct state for suspend/resume icons in debugger
>>
>> I'm trying to implement function in my debugger plugins that is a combination of the CDT debugger attach and launch modes. From the perspective of the CDT debugger, the session looks like a launch, but my plugin is actually attaching to a running process thru an agent that my plugin connects gdb to by having gdb issue a 'target remote' command.
>>
>> I have this working where my plugin establishes the connection, then suspends the running process by issuing an '-exec-interrupt' command. At this point, the user can set breakpoints and resume execution.
>>
>> I am issuing the -exec-interrupt command from the stepRunProgram method in my class that extends StartOrRestartProcessSequence_7_0.
>>
>> The problem is that even though the 'resume' icon is enabled, when I click it, the resume icon is disabled but the 'suspend' icon is not enabled. Once the first breakpoint is reached, the state of the icons is correct and they work correctly.
>>
>> I tried fixing this by getting access to the IDebugTarget object to suspend the application but it seems that it has not been created yet. When I try to access it thru the ILaunch object, its value is null.
>>
>> Then I tried getting access to the IRunControl object and calling its suspend() method,but that resulted in an error message telling me the program was already suspended. I then tried calling the resume() method on the IRunControl object then calling suspend() but that did not help.
>>
>> The other problem I have, maybe related, is that if I click the single step icon and the program suspended somewhere in a library function or then the single step fails with a message from gdb telling me gdb can't determine the bounds of the function. If the program suspends in the application itself, then single step works correctly.
>>
>> I'm looking for suggestion of other ways to approach getting the program into a suspended stare when my plugin connects to it.
>>
>> Thanks
>> Dave
>> _______________________________________________
>> cdt-dev mailing list
>> cdt-dev@xxxxxxxxxxx
>> To change your delivery options, retrieve your password, or unsubscribe from this list, visit
>> https://dev.eclipse.org/mailman/listinfo/cdt-dev
>> _______________________________________________
>> cdt-dev mailing list
>> cdt-dev@xxxxxxxxxxx
>> To change your delivery options, retrieve your password, or unsubscribe from this list, visit
>> https://dev.eclipse.org/mailman/listinfo/cdt-dev











Back to the top