This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH 3/N] remote follow fork and spurious child stops in non-stop mode


Hi Don,

Sorry for the delay.

On 07/24/2015 07:43 PM, Don Breazeal wrote:

>> index 17b2a51..56a33ff 100644
>> --- a/gdb/gdbserver/linux-low.c
>> +++ b/gdb/gdbserver/linux-low.c
>> @@ -488,6 +488,13 @@ handle_extended_wait (struct lwp_info *event_lwp, int wstat)
>>  	  child_lwp->status_pending_p = 0;
>>  	  child_thr = get_lwp_thread (child_lwp);
>>  	  child_thr->last_resume_kind = resume_stop;
>> +	  child_thr->last_status.kind = TARGET_WAITKIND_STOPPED;
> 
> This makes perfect sense to me.
> 

Great.

>> +
>> +	  /* If we're suspending all threads, leave this one suspended
>> +	     too.  */
>> +	  if (stopping_threads == STOPPING_AND_SUSPENDING_THREADS)
>> +	    child_lwp->suspended = 1;
> 
> I have a question about this.  In the definition of struct lwp_info in
> linux-low.h, it has this comment:
> 
>   /* When this is true, we shall not try to resume this thread, even
>      if last_resume_kind isn't resume_stop.  */
>   int suspended;
> 
> Since we are setting last_resume_kind to resume_stop here, is this
> unnecessary?

We still need it, because otherwise we'd decrement the suspend count
below 0:

static int
unsuspend_and_proceed_one_lwp (struct inferior_list_entry *entry, void *except)
{
  struct thread_info *thread = (struct thread_info *) entry;
  struct lwp_info *lwp = get_thread_lwp (thread);

  if (lwp == except)
    return 0;

  lwp->suspended--;
  gdb_assert (lwp->suspended >= 0);

  return proceed_one_lwp (entry, except);
}


It's proceed_one_lwp that skips resuming if the client wants the
lwp stopped:

static int
proceed_one_lwp (struct inferior_list_entry *entry, void *except)
{
...
  if (thread->last_resume_kind == resume_stop
      && thread->last_status.kind != TARGET_WAITKIND_IGNORE)
    {
      if (debug_threads)
	debug_printf ("   client wants LWP to remain %ld stopped\n",
		      lwpid_of (thread));
      return 0;
    }




I tried writing a test for this, by making a multithreaded program
have all its threads but the main continuously fork (see attached), while
the main thread continuously steps over a breakpoint (a conditional
breakpoint with condition "0" should do it, as gdbserver handles
that breakpoint itself), but that stumbles on yet more problems...  :-/

$ ./gdb ./testsuite/gdb.threads/fork-plus-threads-2 -ex "set non-stop on" -ex "set detach-on-fork off" -ex "tar extended-rem :9999"
...
Remote debugging using :9999
(gdb)
[Thread 24971.24971] #1 stopped.
0x0000003615a011f0 in ?? ()
c&
Continuing.
(gdb) [New Thread 24971.24981]
[New Thread 24983.24983]
[New Thread 24971.24982]

[Thread 24983.24983] #3 stopped.
0x0000003615ebc7cc in __libc_fork () at ../nptl/sysdeps/unix/sysv/linux/fork.c:130
130       pid = ARCH_FORK ();
[New Thread 24984.24984]
Error in re-setting breakpoint -16: PC register is not available
Error in re-setting breakpoint -17: PC register is not available
Error in re-setting breakpoint -18: PC register is not available
Error in re-setting breakpoint -19: PC register is not available
Error in re-setting breakpoint -24: PC register is not available
Error in re-setting breakpoint -25: PC register is not available
Error in re-setting breakpoint -26: PC register is not available
Error in re-setting breakpoint -27: PC register is not available
Error in re-setting breakpoint -28: PC register is not available
Error in re-setting breakpoint -29: PC register is not available
Error in re-setting breakpoint -30: PC register is not available
PC register is not available
(gdb)

>>  set test "reached breakpoint"

BTW, I noticed that this test message is stale from my previous attempt
at running to a breakpoint instead of to exit.  I changed it to:

 set test "inferior 1 exited"

in patch 1/2.

>>  gdb_test_multiple "" $test {
>> +    -re "Cannot remove breakpoints" {
>> +	set saw_cannot_remove_breakpoints 1
>> +	exp_continue
>> +    }
>> +    -re "Thread \[^\r\n\]+ stopped\\." {
>> +	set saw_thread_stopped 1
>> +	exp_continue
>> +    }
>>      -re "Inferior 1 \(\[^\r\n\]+\) exited normally" {
>>  	pass $test
>>      }
>>  }

Thanks,
Pedro Alves

Attachment: fork-plus-threads-2.c
Description: Text document


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]