Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 1 Sep 2007 13:26:00 +0200
From:      Jilles Tjoelker <jilles@stack.nl>
To:        Joe Marcus Clarke <marcus@FreeBSD.org>
Cc:        freebsd-arch@FreeBSD.org
Subject:   Re: Understanding interrupted system calls
Message-ID:  <20070901112600.GA33832@stack.nl>
In-Reply-To: <1188600721.1255.11.camel@shumai.marcuscom.com>
References:  <1188600721.1255.11.camel@shumai.marcuscom.com>

next in thread | previous in thread | raw e-mail | index | archive | help
On Fri, Aug 31, 2007 at 06:52:01PM -0400, Joe Marcus Clarke wrote:
> In my attempts to debug the problems with ConsoleKit and the
> VT_WAITACTIVE ioctl, I delved into the tsleep/msleep code, and I think I
> have a pretty good idea when it returns EINTR vs. ERESTART.  However,
> I'm curious as to why I have to do something like the following to allow
> a process waiting in tsleep() to die when it receives a termination
> signal (e.g. SIGTERM or SIGINT):
> 
> struct sigaction sa;
> 
> sa.sa_handler = SIG_DFL;
> ...
> sigaction (SIGTERM, &sa, NULL);
> 
> Shouldn't the ps_sigintr set be initialized to the default set of
> termination signals by default (e.g. in init_main.c proc0_init())?  That
> is, shouldn't the list of signals whose default action is to terminate
> the process (according to signal(3)) be allowed to interrupt a system
> call by default?  If one then wants to restart the syscall, they can
> explicitly do:

> struct sigaction sa;

> sa.sa_flags = SA_RESTART;
> ...
> sigaction (SIGTERM, &sa, NULL);

> I'm just trying to get a better handle on why terminating a program that
> is running the VT_WAITACTIVE ioctl leaves an unkillable process on
> FreeBSD, but apparently just causes the program to terminate on Linux.

The problem seems to be the following code in
src/sys/dev/syscons/syscons.c, in case VT_WAITACTIVE in scioctl():

	while ((error=tsleep(&scp->smode, PZERO|PCATCH,
			     "waitvt", 0)) == ERESTART) ;

If a signal is caught and system call restart is enabled for that
signal, this makes it spin in a tight loop, waiting in vain for the
signal to go away.  The idea of ERESTART is that the syscall function
returns it and then the signal handler is entered.  If and when the
signal handler returns, it will return to the system call instruction,
restarting it (perhaps this is optimized to avoid the switch to userland
and back).  With EINTR, the signal handler would return to directly
after the system call instruction.

The fixed version would then be

	error = tsleep(&scp->smode, PZERO|PCATCH, "waitvt", 0);

I have not tested this, however.

The VT_WAITACTIVE implementation in pcvt
(src/sys/i386/isa/pcvt/pcvt_ext.c) appears to have the same issue (in
RELENG_6; pcvt has been removed from HEAD).

-- 
Jilles Tjoelker



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