[GHC] #7353: Make system IO interruptible on Windows
GHC
cvs-ghc at haskell.org
Wed Oct 31 02:07:14 CET 2012
#7353: Make system IO interruptible on Windows
---------------------------------+------------------------------------------
Reporter: joeyadams | Owner:
Type: bug | Status: new
Priority: normal | Milestone: 7.8.1
Component: libraries/base | Version: 7.6.1
Keywords: | Os: Windows
Architecture: Unknown/Multiple | Failure: Incorrect result at runtime
Difficulty: Unknown | Testcase:
Blockedby: | Blocking:
Related: |
---------------------------------+------------------------------------------
Comment(by joeyadams):
Here's my first shot at the I/O manager: https://github.com/joeyadams
/haskell-iocp .
Replying to [comment:5 simonmar]:
> ... because you'll need one OS thread for each in-progress IO operation,
since all of these OS threads are blocked in the `(Ptr OVERLAPPED -> IO
())` function waiting for the result.
Actually, we don't. We just need to make sure a HANDLE doesn't use the
same OS thread for multiple simultaneous operations. Other than that,
multiple HANDLEs may share a single OS thread. For example, this is okay:
* Worker 1: pending recv for A, pending recv for B
* Worker 2: pending send for A
But this is not okay:
* Worker 1: pending recv for A, pending recv for B, ''pending send for
A''
In the second scenario, if we issue !CancelIo on A, it will cancel both
pending jobs, not just the one we want to cancel.
There is only one thread that is expected to block for extended periods of
time, and that is the completion handler, which waits for completions by
calling !GetQueuedCompletionStatus. Starting and canceling overlapped I/O
should not block.
> We expect it to be rare to have multiple outstanding IO requests on the
same HANDLE though - maybe you could even make it an error.
Actually, this can happen if the program needs to send a message while it
is waiting to receive a message. I suppose we could have threads for
different classes of operation (e.g. send, receive, control).
Instead, this is implemented with a nifty trick involving lazy IO. We
create an infinite list of workers using interleaved IO, and have each
IOCPHandle maintain its own free list of workers. Thus, handles share
workers, and new workers are created automatically as needed.
One problem I'd like to address: callers currently can't use functions
like [http://hackage.haskell.org/packages/archive/base/latest/doc/html
/Foreign-Marshal-Alloc.html#v:alloca alloca] to allocate buffers for
overlapped I/O. Moreover,
[http://hackage.haskell.org/packages/archive/base/latest/doc/html/System-
IO.html#v:hPutBuf hPutBuf] would have to copy the data into a temporary
buffer.
This is because the OS owns the buffer until a completion arrives, even in
the case of cancellation. Thus, the application thread should wait for
!CancelIo to complete (the implementation currently doesn't do this).
This should be easy to fix: on exception, tell the worker thread to
!CancelIo, and signal our MVar when it's done. Use uninterruptibleMask_
(takeMVar mv) to wait for the signal. This will also simplify the
lifetime of completion objects and worker allocations.
But is it safe? It should be if my assumptions are correct:
* Starting overlapped I/O and calling !CancelIo do not block. We have to
make this assumption anyway, if we are going to let handles share worker
threads.
* uninterruptibleMask_ (takeMVar mv) succeeds when another bound thread
fills the MVar. That is, the bound thread won't be blocked due to our use
of uninterruptibleMask_, as it is running from a different OS thread.
* uninterruptibleMask is indeed not interruptible.
Are my assumptions about uninterruptibleMask true?
--
Ticket URL: <http://hackage.haskell.org/trac/ghc/ticket/7353#comment:6>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the Glasgow-haskell-bugs
mailing list