Problems interrupting IO with -threaded
marlowsd at gmail.com
Wed Jun 11 00:43:33 EDT 2008
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
More information about the Glasgow-haskell-users