Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 9 Oct 2007 16:49:00 -0700 (PDT)
From:      Matthew Dillon <dillon@apollo.backplane.com>
To:        Kostik Belousov <kostikbel@gmail.com>
Cc:        arch@freebsd.org
Subject:   Re: Abolishing sleeps in issignal()
Message-ID:  <200710092349.l99Nn01S073431@apollo.backplane.com>
References:  <20071008142928.Y912@10.0.0.1> <20071009100259.GW2180@deviant.kiev.zoral.com.ua>

next in thread | previous in thread | raw e-mail | index | archive | help
    I think it's a bad idea to have SIGSTOP generate an EINTR-like event.
    The two have totally different mechanics and the system call behavior
    will be different because there are some system calls which simply cannot
    be restarted even if you wanted to.  System calls which loop on UIO's,
    for example, cannot be restarted.  EINTR and STOP have two totally
    different behaviors for such calls and there is nothing you can do about
    it.  Basically any system call which maintains state through multiple
    blocking events cannot be restarted after having returned unless no
    cumulative operations have been performed.

    For example, if read()ing from a socket the read() is restartable ONLY
    if no data has yet been read.  But if some data HAS been read and EINTR
    occurs, the system call will simply terminate early and return a
    short-read, and NOT restart.  That same system call when presented with
    a STOP, however, will not terminate early.  Instead it (in FreeBSD now)
    stops in tsleep and when it is CONTed again the system call resumes.
    It's simply not possible (without a LOT of work) to have such a system
    call return all the way to userland or even return to the kernel syscall
    trap layer and be able to restart it.

    The restart code only works if no cumulative events have occured... for
    example, if a UIO has not been filled at all (0 bytes read or written).
    ERESTART literally moves the program counter back to the start of the
    system call and causes userland to re-execute it.

    The best compromise that I found, which I implemented for Dragonfly a
    while back, was to ignore SIGSTOP in the kernel entirely and process
    the event in userret() instead.  Except for certain process control
    cases like the debugger, SIGSTOP is handled asynchronously anyway. e.g.
    when you signal a SIGSTOP the kill() system call will return before
    the target process(es) have actually stopped.  It's just that the window
    of opportunity is fairly small when SIGSTOP is handled in tsleep, and
    somewhat bigger when it is handled in userret.  That's the only hangup.

						-Matt




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