Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 7 Jan 2002 17:16:42 +1100 (EST)
From:      Bruce Evans <bde@zeta.org.au>
To:        Peter Wemm <peter@wemm.org>
Cc:        Archie Cobbs <archie@dellroad.org>, Alfred Perlstein <bright@mu.org>, Dan Eischen <eischen@vigrid.com>, <arch@FreeBSD.ORG>
Subject:   Re: Request for review: getcontext, setcontext, etc 
Message-ID:  <20020107164848.J468-100000@gamplex.bde.org>
In-Reply-To: <20020106232937.9F87D38CC@overcee.netplex.com.au>

next in thread | previous in thread | raw e-mail | index | archive | help
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 void
catch(int sig)
{
	char buf[4 * 1024 * 1024];	/* Large to use up stack fast. */
	sigset_t omask;

	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);
	if (sigsetjmp(jb, 1) == 0)
		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).

> 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?).
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


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?20020107164848.J468-100000>