#2189: hSetBuffering stdin NoBuffering doesn't work on Windows
--------------------------------------------+-------------------------------
Reporter: FalconNL | Owner:
Type: bug | Status: new
Priority: high | Milestone: 6.10.2
Component: libraries/base | Version: 6.8.2
Severity: normal | Resolution:
Keywords: hsetbuffering buffering buffer | Difficulty: Unknown
Testcase: | Architecture: x86
Os: Windows |
--------------------------------------------+-------------------------------
Changes (by Deewiant):
* cc: Deewiant (added)
* summary: hSetBuffer stdin NoBuffering doesn't seem to work in ghc
6.8.2 on Windows XP => hSetBuffering stdin
NoBuffering doesn't work on Windows
Comment:
Unfortunately conio doesn't mix with ordinary IO, as I demonstrated in a
response to that thread on glasgow-haskell-users.
As for the original problem, I think this'd take some work to solve: GHC
would have to convert to the Win32 API for all of its IO on Windows.
(That'd also help with #806.)
What currently happens is the following call chain, starting from
`hGetChar` (a bit of documentation for any would-be fixers):
{{{
System.IO.hGetChar stdin
-- meanings of numbers: stdin FD, not a socket, offset 0, length 1
GHC.Handle.readRawBuffer "hGetChar" 0 0 <buffer> 0 1
GHC.Handle.asyncReadRawBuffer 0 0 <buffer> 0 1
GHC.Conc.asyncReadBA 0 0 1 0 <buffer>
-- offset got applied
GHC.Conc.asyncRead 0 0 1 <buffer>
-- asyncReadzh_fast in rts/PrimOps.cmm
asyncRead# 0 0 1 <buffer>
-- in rts/win32/AsyncIO.c
-- the new 0 signifies that this is a read and not a write
addIORequest(0, 0, 0, 1, <buffer>)
}}}
From there it ends up into the asynchronous IO work queue, whence it
eventually gets picked up by `IOWorkerProc` (in rts/win32/IOManager.c). It
notices that the `workKind` is `WORKER_READ` but not `WORKER_FOR_SOCKET`,
so it does a plain `read()` call.
In the current situation that's basically fine, since the `hSetBuffering`
never did anything and we're still in line buffered mode. In unbuffered
mode, that'd be a problem, as the comment from System.Posix.Internals
(which judah posted above) asserts: enter needs to be pressed twice. The
fact that it gives '\r' instead of '\n' isn't such a big problem since it
can be easily modified.
I'm attaching a C program which shows how the problem is avoided by using
the Win32 API directly (in this case, `ReadFile` is fine) instead of the
POSIX `read`: the latter requires two presses of enter, the former only
one.
Since there seems to be no way of getting a Win32 `HANDLE` object from a C
`FILE*` let alone a POSIX file descriptor, I believe that the only
reasonable way of getting this and #806 to work reliably is to convert the
whole IO subsystem to use the Windows API directly—starting from changing
`GHC.IOBase.Handle__.haFD` from an `FD` to a `HANDLE` on Windows.
--
Ticket URL: <http://hackage.haskell.org/trac/ghc/ticket/2189#comment:12>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler_______________________________________________
Glasgow-haskell-bugs mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/glasgow-haskell-bugs