On Wed, Nov 27, 2019 at 08:33:53PM +0000, Konstantin Belousov wrote:
> Author: kib
> Date: Wed Nov 27 20:33:53 2019
> New Revision: 355146
> URL: https://svnweb.freebsd.org/changeset/base/355146
Ease the life of PTRACE_SYSCALL users when debuggee sleeps in
sigsuspend(2) and sig{timed,}wait(2).

If PT_TO_SCE or PT_TO_SCX were issued after the target already entered
sleep in sigsuspend(2) or sigtimedwait(2), there is no debugging
events generated until a relevant signal is delivered.  As result,
debugger hangs waiting for an event.

Introduce spurious EINTR returned in that situations to help debugger
to gain control earlier.

[Sorry]
> 
> Log:
>   Requested and tested by:    kevans
>   Reviewed by:        kevans (previous version), markj
>   Sponsored by:       The FreeBSD Foundation
>   MFC after:  1 week
>   Differential revision:      https://reviews.freebsd.org/D22546
> 
> Modified:
>   head/sys/kern/kern_sig.c
> 
> Modified: head/sys/kern/kern_sig.c
> ==============================================================================
> --- head/sys/kern/kern_sig.c  Wed Nov 27 20:33:49 2019        (r355145)
> +++ head/sys/kern/kern_sig.c  Wed Nov 27 20:33:53 2019        (r355146)
> @@ -65,6 +65,7 @@ __FBSDID("$FreeBSD$");
>  #include <sys/namei.h>
>  #include <sys/proc.h>
>  #include <sys/procdesc.h>
> +#include <sys/ptrace.h>
>  #include <sys/posix4.h>
>  #include <sys/pioctl.h>
>  #include <sys/racct.h>
> @@ -1252,11 +1253,13 @@ kern_sigtimedwait(struct thread *td, sigset_t waitset,
>       int error, sig, timo, timevalid = 0;
>       struct timespec rts, ets, ts;
>       struct timeval tv;
> +     bool traced;
>  
>       p = td->td_proc;
>       error = 0;
>       ets.tv_sec = 0;
>       ets.tv_nsec = 0;
> +     traced = false;
>  
>       if (timeout != NULL) {
>               if (timeout->tv_nsec >= 0 && timeout->tv_nsec < 1000000000) {
> @@ -1309,6 +1312,11 @@ kern_sigtimedwait(struct thread *td, sigset_t waitset,
>                       timo = 0;
>               }
>  
> +             if (traced) {
> +                     error = EINTR;
> +                     break;
> +             }
> +
>               error = msleep(ps, &p->p_mtx, PPAUSE|PCATCH, "sigwait", timo);
>  
>               if (timeout != NULL) {
> @@ -1320,6 +1328,16 @@ kern_sigtimedwait(struct thread *td, sigset_t waitset,
>                               error = 0;
>                       }
>               }
> +
> +             /*
> +              * If PTRACE_SCE or PTRACE_SCX were set after
> +              * userspace entered the syscall, return spurious
> +              * EINTR after wait was done.  Only do this as last
> +              * resort after rechecking for possible queued signals
> +              * and expired timeouts.
> +              */
> +             if (error == 0 && (p->p_ptevents & PTRACE_SYSCALL) != 0)
> +                     traced = true;
>       }
>  
>       new_block = saved_mask;
> @@ -1532,6 +1550,14 @@ kern_sigsuspend(struct thread *td, sigset_t mask)
>                       has_sig += postsig(sig);
>               }
>               mtx_unlock(&p->p_sigacts->ps_mtx);
> +
> +             /*
> +              * If PTRACE_SCE or PTRACE_SCX were set after
> +              * userspace entered the syscall, return spurious
> +              * EINTR.
> +              */
> +             if ((p->p_ptevents & PTRACE_SYSCALL) != 0)
> +                     has_sig += 1;
>       }
>       PROC_UNLOCK(p);
>       td->td_errno = EINTR;
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to