Skip to content

hGetBufNonBlocking blocks the underlying handle on Windows

In a cross-platform transport-layer proxy software I am developing, I have this piece of code:

  a >- b $ j       -- forks
  b >- a $ j       -- forks

where a and b are handles; j is an exception handler and (>-) is a self-forking infinite loop IO that splices data between two handles, defined previously in terms of hGetBufSome and and hPutBuf on Windows.

I just noticed that:

  b >- a $ j       -- forks
  a >- b $ j       -- forks

behaves differently from:

  a >- b $ j       -- forks
  b >- a $ j       -- forks

When proxying connections to an SSH server the first one does not show the greeting from the SSH server before receiving user input, the second does show the greeting.

As the two lines immediately fork to their own Haskell threads the blocking must come from the underlying handles.

When I attempted to use hGetBufNonBlocking to avoid the problem I noticed that the docs read: "NOTE: on Windows, this function does not work correctly; it behaves identically to hGetBuf.".

The reason I chose to use handles in the first place was the "Improving I/O Performance over sockets" section in the network package: http://hackage.haskell.org/packages/archive/network/2.3.0.13/doc/html/Network.html.

At this point I am stuck as neither the network package exports functions that work on pointers to pre-allocated memory buffers nor the h---- famiy of functions from System.IO behave as their names suggest.

Defining (>-) in terms of recv and sendAll from Network.Socket.ByteString does show the problem and both variants behave exactly the same at run time and this is the only correct behaviour as I have no way of knowing or special-casing which application layer protocols expect initiation from which end (client input first or server greeting first).

I am reporting this issue to both here and to the maintainers of the network package on GitHub .

This bug is reported for 7.0.4 but I highly suspect the behavior may still be the same with newer GHC versions.

Trac metadata
Trac field Value
Version 7.0.4
Type Bug
TypeOfFailure OtherFailure
Priority normal
Resolution Unresolved
Component libraries/base
Test case
Differential revisions
BlockedBy
Related
Blocking
CC
Operating system
Architecture
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information