[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