POSIX world's signal handlers and EINTR error don't map well onto Scheme world,
and I feel we need some baseline agreement on Scheme-side semantics of them
to write portable code.
Short summary:
(1) Make Scheme signal handler free from limitations of what you can do in POSIX
signal handler.
(2) We could make the runtime restart the interrupted system calls If we want to
abort the call we can just jump out from the Scheme signal handler.
Discussion:
It is not trivial to run Scheme code in system's signal handler---you can't
call any Scheme runtime that can call non async-signal-safe functions,
and probably you can't throw an exception or invoke a continuation captured
outside the handler.
One option is to let the system's signal handler to set a flag indicating
the signal is delivered, and later, at the "safe" point, check the flag and invoke
Scheme signal handler if necessary. This doesn't work with synchronous signals,
but they're out of scope of srfi-170.
If we take this option, handling of EINTR needs care; if we just throw an exception
immediately when a syscall returns an error, the exception is raised before a Scheme
signal handler is ever called, which doesn't seem to be very useful. At least,
the implementation should check the signal delivery and invoke Scheme signal
handler necessary when a syscall returns an error with errno = EINTR.
However, if you handle the signal, most of the time you want to restart the syscall.
Since signal can be delivered anywhere unless blocked, you'll make sure to installl
exception handler that effectively ignores EINTR exception. I feel it's more sensible
to make the runtime restarts the syscall if it returns an error with EINTR, instead
of throwing an exception on it. Note that if you want otherwise, that is, you don't
want to restart the syscall, you can just throw your own exception from the signal handler.
Note: If the runtime uses signals internally to synchronize threads, for example,
by the garbage collector, it is normal that syscalls are interrupted, and they shouldn't
cause exceptions but should silently restarted. It will be cumbersome if the runtime
needs to distinguish such normal interrupt from other interrupts. Restart on EINTR
policy just covers the normal interrupt cases as well.
There are a few POSIX syscalls that doesn't go well with this delayed-signal-handling
and automatic restarting, though they're not included in srfi-170.
I list them for the future reference.
- pause() - the whole point of pause() is to be interrupted, so restarting it on EINTR
doesn't make sense. Furthermore, since execution of Scheme signal handler
is delayed, there's a chance that a signal delivered after the last check and
the call to pause() may not be handled timely. In Gauche I abandoned using pause()
and implemented on top of sigsuspend().
- sleep(), nanosleep() - If these calls are interrupted, they return the remaining time.
We have to use those remaining time to restart the call.