Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 07 Jan 2002 04:51:27 -0500
From:      Dan Eischen <eischen@vigrid.com>
To:        Bruce Evans <bde@zeta.org.au>
Cc:        Peter Wemm <peter@wemm.org>, Archie Cobbs <archie@dellroad.org>, Alfred Perlstein <bright@mu.org>, arch@FreeBSD.ORG
Subject:   Re: Request for review: getcontext, setcontext, etc
Message-ID:  <3C396F9F.A53049E4@vigrid.com>
References:  <20020107164848.J468-100000@gamplex.bde.org>

next in thread | previous in thread | raw e-mail | index | archive | help
Bruce Evans wrote:
> 
> On Sun, 6 Jan 2002, Peter Wemm wrote:
> 
> > The context argument passed in to signal handlers should be able to be used
> > with setcontext() to return from the signal handler as an alternative to
> > sigreturn().  Doing it in libc wont work there because you race with
> > restoring the signal mask before you've finished setting the application
> > state.
> 
> The i386 siglongjmp() gets this wrong despite using a syscall (sigprocmask):
> 
> %%%
> #define _POSIX_SOURCE   1
> 
> #include <setjmp.h>
> #include <signal.h>
> #include <string.h>
> #include <unistd.h>
> 
> sigjmp_buf jb;
+ static int	jb_valid = 0;
> 
> static void
> catch(int sig)
> {
>         char buf[4 * 1024 * 1024];      /* Large to use up stack fast. */
>         sigset_t omask;
> 
+         if (jb_valid != 0) {
+         jb_valid = 0;
>         sigprocmask(SIG_BLOCK, NULL, &omask);
>         sprintf(buf, "caught signal %d @ %p; signal mask %#x\n",
>             sig, (void *)&buf[0], *(unsigned *)&omask); /* XXX */
>         write(1, buf, strlen(buf));
>         kill(getpid(), sig);            /* Simulate a race. */
>         sprintf(buf, "signals apparently masked correctly before siglongjmp\n");
>         write(1, buf, strlen(buf));
>         siglongjmp(jb, 1);
+         }
> }
> 
> int
> main(void)
> {
>         struct sigaction sa;
> 
>         sa.sa_flags = 0;
>         sigemptyset(&sa.sa_mask);
>         sa.sa_handler = catch;
>         sigaction(SIGUSR1, &sa, NULL);
/* here a signal can occur with jb uninitialized! */
>         if (sigsetjmp(jb, 1) == 0)
+         {
+ 		  jb_valid = 1;
>                 kill(getpid(), SIGUSR1);
          }
>         return (0);
> }
> %%%
> 
> Myabe this can be fixed by restoring %esp before calling sigprocmask;
> otherwise siglongjmp needs to use sigreturn (or the corresponding syscall
> that restores the whole ucontext).

I don't really see how having the *context() or *jmp() routines be
a syscall helps.  You still have to protect the accesses to the
jmp_buf or ucontext for race conditions regardless of whether these
functions are syscalls or not.  There's a few instructions to be
executed after leaving the kernel via a system call anyways, right?
You could always get preempted there and have another signal be
delivered.

> > Also, I noticed that the i386 patch doesn't save FP state (!) which is
> > one of the primary reasons for get/setcontext().  I'm not sure if this
> > can be efficiently done since this user-level function will not know if
> > the current context has touched the FPU yet..
> 
> I think doing it in userland basically forces you to do physical FPU
> accesses using fnsave/frstor (and something different for the SSE case?).

We do this in libc_r right now.  When a signal is caught, we use fnsave
to save the FP regs to the ucontext area (knowing the kernel doesn't
do it for us -- shouldn't it be saving the FP regs?).  We remember
that the threads context has FP regs saved in this case and use
frstor when it is resumed.  Threads interrupted by signals are the
only case (for i386) that FP regs are saved and restored.

> The case where a syscall would be most efficient (when the FPU is not used)
> will be especially inefficient since it will have to trap to the kernel
> anyway to access the state.
> 
> Bruce

-- 
Dan Eischen

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-arch" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?3C396F9F.A53049E4>