[MLton] interrupted system call
Stephen Weeks
MLton@mlton.org
Wed, 24 Mar 2004 11:43:13 -0800
> re too expensive, my interpretation of Matthews thought was that we
> alway run with all signals blocked (more on that below), but when
> the current code checks to see if a signal has occured, instead we
> unblock the signals and then immediately reblock them and then check
> the flag.
My interpretation was that the MLton C signal handler, GC_handler,
would block all signals (I assume this is OK in a C signal handler, is
it?). Then, GC_finishHandler would unblock them, as it does now.
This would prevent a system call from being interrupted by a signal
more than once.
> The problem is that unblocking and then reblocking signals would
> mean two system calls (both sigblock()) and that is probably too
> expensive.
Ahh, I think I understand. We currently rely on GC_handler to set
limit to zero so that we fail the next limit check. Your approach
would imply changing our very fast limit check (a single compare) to
two system calls. Yes, that is unacceptable.
Here's another option: block the signals if the the system call is
interrupted, so that the restart can't be interrupted. Something like
val Posix.Error.syscall: (unit -> int) -> int =
fn f =>
let
fun call (err: int -> int): int =
let
val n = f ()
in
if n = ~1 then err (getErrno ()) else n
end
in
call (fn e =>
if e = intr orelse e = restart
then (blockSignals ()
; dynamicWind (fn () => call raiseSys, unblockSignals))
else raiseSys e)
end
That way we only pay the two system calls if the original system call
is interrupted. We dont pay for limit checks or for
atomic{Begin,End}.
> With regards to `all signals blocked', note that C libraries must be handling
> interrupts. I guess that the right thing would be to only block signals that
> are handled by ML code.
Makes sense.