Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 24 May 2014 00:35:10 +0200
From:      Jilles Tjoelker <jilles@stack.nl>
To:        Konstantin Belousov <kostikbel@gmail.com>
Cc:        Keno Fischer <kfischer@college.harvard.edu>, freebsd-hackers@freebsd.org, Benjamin Kaduk <kaduk@MIT.EDU>
Subject:   Re: Use of sigreturn(2) in longjmp(3).
Message-ID:  <20140523223509.GB29378@stack.nl>
In-Reply-To: <20140522155418.GX74331@kib.kiev.ua>
References:  <CAEoGj__-4A9KwqmjnOdEBfjxheJFpHV8ivo7o4n3ChcxeEq1oQ@mail.gmail.com> <alpine.GSO.1.10.1405221124380.25244@multics.mit.edu> <20140522155418.GX74331@kib.kiev.ua>

next in thread | previous in thread | raw e-mail | index | archive | help
On Thu, May 22, 2014 at 06:54:18PM +0300, Konstantin Belousov wrote:
> On Thu, May 22, 2014 at 11:25:32AM -0400, Benjamin Kaduk wrote:
> > On Thu, 22 May 2014, Keno Fischer wrote:

> > > The sigreturn manpage states:

> > > "This system call is used by the trampoline code and longjmp(3) when
> > > returning from a signal to the previously executing program".

> > > Now, I saw the system call in sigtramp.s, but I looked at setjmp.s can't
> > > find how longjmp does this. Am I missing something totally obvious?

> > I expect this is just stale documentation.
> > Unfortunately, some quick poking at the svn log for 
> > sys/i386/i386/support.s does not make it immediately clear when the code 
> > changed to not match the documentation.

> support.s is not related to the issue discussed.

> Theoretically, sigreturn(2) might be required on some architectures,
> where the raw access to the usermode CPU state requires supervisor CPU
> state. AFAIK all architectures FreeBSD runs on either do not have this
> quirk, or limit the state saved and restored in the setjmp/longjmp
> functions, to the state accessible to the usermode.

> For instance, even on x86, the TLS base is not saved and consequently
> not restored by *jmp(3), and cannot be accessed directly by usermode,
> while sigreturn(2) allows to perform full context modification, including
> TLS base.

> Some implementations of longjmp(3)-like functionality, e.g. the one
> provided by libunwind, do utilize sigreturn(2) to unwind over the signal
> frame.

The remark about sigreturn(2) is part of a TODO comment. It would be
better to use some sort of system call to restore the signal mask,
program counter and stack pointer in one operation so that stack usage
is reduced if the new mask permits more signal handlers.

For example, if a program uses longjmp() in a SIGINT handler to return
to the top level, the current code allows the SIGINT handler to be
re-entered between the _sigprocmask call and the final return
instruction in the longjmp() function. If this happens repeatedly, a
stack overflow could result. If the signal handler returns normally, the
sigreturn(2) system call restores the signal mask and stack pointer in
one operation, so the problem does not occur.

Using sigreturn(2) for this purpose would require trickery for the FPU
and may be slower than the current implementation.

Regarding the TLS base, saving and restoring it does not seem to make
much sense since the TLS base is constant for each thread and it is not
permitted to longjmp() to an environment saved by a different thread.
Regarding the other segment registers and base, I don't think it's worth
the performance decrease and ABI break to save them for a few special
programs that use them.

-- 
Jilles Tjoelker



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