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 |