Judah Jacobson wrote:
Hi all,
I'm writing a program that reads input from the user but should also
handle a ctrl-c. My attempt is below; the program forks a thread to
read one character of input, and kills that thread upon receiving a
sigINT. It works fine compiled without -threaded, but with -threaded
it blocks forever after a ctrl-c.
I know that in general, foreign calls are not interruptible; but the
documentation for Control.Concurrent and System.Timeout suggests that
I/O operations are a special case. In particular, the documentation
for System.Timeout.timeout says:
"Standard I/O functions like hGetBuf, hPutBuf, Network.Socket.accept,
or hWaitForInput appear to be blocking, but they really don't because
the runtime system uses scheduling mechanisms like select(2) to
perform asynchronous I/O, so it is possible to interrupt standard
socket I/O or file I/O using this combinator."
So is the behavior that I'm seeing correct? If so, it seems odd to
get better concurrency without the threaded runtime. If not, I can
file a bug for this. I used ghc-6.8.2 and HEAD on OS X 10.5 (x86).
Ah, this is a consequence of the change we made to stdin/stdout/stderr
so that they no longer use O_NONBLOCK, but with -threaded they use
blocking foreign calls instead. In your example, getChar is stuck in a
blocking foreign call and can't be interrupted.
I don't see a good workaround. One way is to add another thread: run
the getChar in a subthread and the parent will be able to receive the
signal. Or perhaps you could cause the read() that getChar has called
to return EINTR, but that might not be enough because the I/O library
executes mostly inside Control.Exception.block.
Unix semantics just isn't the right thing when it comes to non-blocking
I/O. If only there were non-blocking read()/write() system calls, we'd
be fine.
Cheers,
Simon
_______________________________________________
Glasgow-haskell-users mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/glasgow-haskell-users