Re: [PATCH] [RFC, docs RFA] gdbserver and gdb.threads/attach-into-signal.exp.

Yao Qi
2012-02-23T03:32:47Z

On 02/23/2012 01:19 AM, Pedro Alves wrote:
> The issue is that when GDBserver detaches the inferior, it forgets the
> SIGALRM signal it had found when it attached, so the inferior doesn't
> get the signal (it is suppressed) and reaches the abort. The fix is
> to make sure we forward the pending signals to the inferior on detach,
> like gdb/linux-nat.c does. gdb/linux-nat.c does not pass down to the
> inferior signals that are in the "handle SIG nopass" state, however.
> GDBserver has no idea currently about the pass/nopass state of
> signals, so in order for GDBserver to do the same GDB, we need to make
> GDB tell GDBserver about the pass/nopass state of all signals. This
> is recorded in GDB in the infrun.c:signal_program array. The patch
> adds a new RSP packet QProgramSignals (similar to QPassSignals, though
> with different semantics) to do exactly that.
>

Can we install target_ops hook to_program_signals in linux-nat, and move
existings code in it? As you said, this problem doesn't exit on
linux-nat, and a new target_ops hook to_program_signals is created, so
it is natural to move existing linux-nat code to
linux_nat_program_signals (it is to be created).

> diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
> index ab34d84..5353cff 100644
> --- a/gdb/gdbserver/linux-low.c
> +++ b/gdb/gdbserver/linux-low.c
> @@ -928,36 +928,125 @@ linux_kill (int pid)
> return 0;
> }
>
> +/* Get pending signal of LP, for detaching purposes. */
^^ "THREAD"
Can we remove the 2nd half of this setense "for detaching purpose".
IIUC, this routine is quite general, so it might be used for other
purpose in the future.

> +
> +static int
> +get_pending_signal (struct thread_info *thread)

> +
> static int
> linux_detach_one_lwp (struct inferior_list_entry *entry, void *args)
> {
> struct thread_info *thread = (struct thread_info *) entry;
> struct lwp_info *lwp = get_thread_lwp (thread);
> int pid = * (int *) args;
> + int sig;
>
> if (ptid_get_pid (entry->id) != pid)
> return 0;
>
> - /* If this process is stopped but is expecting a SIGSTOP, then make
> - sure we take care of that now. This isn't absolutely guaranteed
> - to collect the SIGSTOP, but is fairly likely to. */
> + /* If there is a pending SIGSTOP, get rid of it. */
> if (lwp->stop_expected)
> {
> - int wstat;
> - /* Clear stop_expected, so that the SIGSTOP will be reported. */
> + if (debug_threads)
> + fprintf (stderr,
> + "Sending SIGCONT to %s\n",
> + target_pid_to_str (ptid_of (lwp)));
> +
> + kill_lwp (lwpid_of (lwp), SIGCONT);
> lwp->stop_expected = 0;
> - linux_resume_one_lwp (lwp, 0, 0, NULL);
> - linux_wait_for_event (lwp->head.id, &wstat, __WALL);
> }
>

As described in changelog entry,

(linux_detach_one_lwp): Get rid of a pending SIGSTOP with SIGCONT.
Pass on pending signals to PTRACE_DETACH.

Pending SIGSTOP is replaced with (pending?) SIGCONT. In original code,
resume lwp -> wait -> PTRACE_DETACH (0). With this patch, it changed to
PTRACE_DETACH (SIGCONT) directly, IIUC. I am wondering it may the
status of program after detach, especiall when attach to a `T (stopped)'
process at the beginning of debug session. I am unable to find a test
case to proof, so I may be wrong. Just rise this question here.

> /* Flush any pending changes to the process's registers. */
> regcache_invalidate_one ((struct inferior_list_entry *)
> get_lwp_thread (lwp));
>
> + /* Pass on any pending signal for this thread. */
> + sig = get_pending_signal (thread);
> +
> /* Finally, let it resume. */
> if (the_low_target.prepare_to_resume != NULL)
> the_low_target.prepare_to_resume (lwp);
> - ptrace (PTRACE_DETACH, lwpid_of (lwp), 0, 0);
> + if (ptrace (PTRACE_DETACH, lwpid_of (lwp), 0, sig) < 0)
> + error (_("Can't detach %s: %s"),
> + target_pid_to_str (ptid_of (lwp)),
> + strerror (errno));
>
> delete_lwp (lwp);
> return 0;

--
Yao (é½å°§)