Re: Stepping of multithreaded application

Pedro Alves
2011-05-16T11:17:56Z

On Thursday 12 May 2011 11:44:50, Tomas Martinec wrote:
> >> That is not supported in the virtual machine
> >> and the machine responds so. I believe not supporting the Hc0 command
> >> is not wrong for the virtual machine.
> >
> > IMO, it's wrong. But I don't think it'd make a difference, unless
> > the target gives preference to the already/previously selected
> > Hg/c thread.
>
> > In any case, you should really teach your VM about the vCont
> > packet instead of 'Hc'/'s'/'c'.
>
> I will implement both the Hc0 and vCont in the virtual machine. But at
> first I will try to make just the Hc/s/c commands working.
>
> > Please try the patch below. It's "any_thread_ptid" that causes "Hc0".
> > If we're stepping, obviously we need to step the correct thread, not
> > a random one. I don't really understand how this hasn't been a
> > problem before.
>
> There was another problem after applying the patch. The GDB resumed
> the thread 1 after the thread 3 stepped. I think I have made a fix:
>
> --- infrun_old.c 2010-08-31 21:31:23.000000000 +0200
> +++ infrun.c 2011-05-12 12:20:15.000000000 +0200
> @@ -3513,6 +3513,8 @@
> singlestep_breakpoints_inserted_p = 0;
> }
>
> + ecs->event_thread->trap_expected = 0;
> +
> /* Note: We do not call context_switch at this point, as the
> context is already set up for stepping the original thread. */
> switch_to_thread (deferred_step_ptid);
>
> The trap_expected flag of the thread 1 was not cleared after the step
> of thread 1. Therefore the code has run into the following branch
> during step handling of the thread 3:

This makes sense. However ...

>
> infrun.c: line 4182
>
> /* In all-stop mode, if we're currently stepping but have stopped in
> some other thread, we need to switch back to the stepped thread. */
> if (!non_stop)
> {
> struct thread_info *tp;
>
> tp = iterate_over_threads (currently_stepping_or_nexting_callback,
> ecs->event_thread);
> if (tp)
> {
> // this branch is done, which is wrong; it is done,
> because the thread 1
> // has trap_expected set and therefore the thread is
> considered to be stepping
> //
> // the thread 1 is resumed in this branch; in my case
> the thread 3 never finishes stepping

When I try this (without your patch on x86_64-linux native, I see
is:

Breakpoint 1, thread0 (arg=0x0) at loop.c:39
39 (*myp) ++;
(gdb) info threads
Id Target Id Frame
3 Thread 0x7ffff703a700 (LWP 27787) "loop" 0x00007ffff78e620d in nanosleep () from /lib/libc.so.6
* 2 Thread 0x7ffff783b700 (LWP 27786) "loop" thread0 (arg=0x0) at loop.c:39
1 Thread 0x7ffff7fd5700 (LWP 27783) "loop" 0x00007ffff7bc7285 in pthread_join () from /lib/libpthread.so.0
(gdb) t 3
[Switching to thread 3 (Thread 0x7ffff703a700 (LWP 27787))]
#0 0x00007ffff78e620d in nanosleep () from /lib/libc.so.6
(gdb) n
infrun: clear_proceed_status_thread (Thread 0x7ffff703a700 (LWP 27787))
infrun: clear_proceed_status_thread (Thread 0x7ffff783b700 (LWP 27786))
infrun: clear_proceed_status_thread (Thread 0x7ffff7fd5700 (LWP 27783))
Single stepping until exit from function nanosleep,
which has no line number information.
infrun: proceed (addr=0xffffffffffffffff, signal=144, step=1)
thread_function1: 8
thread_function0: 10
infrun: resume (step=1, signal=0), trap_expected=1
infrun: wait_for_inferior ()
infrun: target_wait (-1, status) =
infrun: 27783 [Thread 0x7ffff783b700 (LWP 27786)],
infrun: status->kind = stopped, signal = SIGTRAP
infrun: infwait_normal_state
infrun: TARGET_WAITKIND_STOPPED
infrun: stop_pc = 0x400741
infrun: handling deferred step
infrun: resume (step=1, signal=0), trap_expected=0
infrun: prepare_to_wait
infrun: target_wait (-1, status) =
infrun: 27783 [Thread 0x7ffff703a700 (LWP 27787)],
infrun: status->kind = stopped, signal = SIGTRAP
infrun: infwait_normal_state
infrun: TARGET_WAITKIND_STOPPED
infrun: stop_pc = 0x7ffff78e620d
infrun: switching back to stepped thread
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

This is indeed wrong.

infrun: Switching context from Thread 0x7ffff703a700 (LWP 27787) to Thread 0x7ffff783b700 (LWP 27786)
infrun: resume (step=0, signal=0), trap_expected=0

We end up continuing all threads (turn on 'set debug lin-lwp'
to get more debug detail), not stepping or continuing
a single thread. This `resume' call clears "trap_expected",
and everything happens to work.

I imagine you're seeing a 'Hc1', 'c', and only continuing
thread 1 instead of all threads? This is part of the
ambiguity with Hc/c/s that vCont fixes...

> The debugging seems to be fine after applying my fix. Still I think
> somebody more familiar with the GDB should review it.

I'll test and apply your fix if nothing turns up regardless.

--
Pedro Alves