Ticket #1198 (closed bug: fixed)

Opened 6 years ago

Last modified 5 years ago

Windows: hWaitForInput returns False for file handles, and doesn't work properly for consoles

Reported by: igloo Owned by: simonmar
Priority: low Milestone: 6.10.1
Component: libraries/base Version: 6.6
Keywords: Cc:
Operating System: Windows Architecture: Unknown/Multiple
Type of failure: Difficulty: Unknown
Test Case: readwrite002, hReady001 Blocked By:
Blocking: Related Tickets:

Description

On Windows, readwrite002 is failing with

readwrite002.exe: readwrite002.inout: hWaitForInput: invalid argument (Invalid argument)

The error is being generated by

rc = PeekNamedPipe( hFile, NULL, 0, NULL, &avail, NULL );

in the inputReady function in cbits/inputReady.c, during a call to hReady.

Change History

  Changed 6 years ago by simonmar

  • owner set to simonmar

I have a partial fix waiting for validation

  Changed 6 years ago by simonmar

  • owner simonmar deleted
  • priority changed from normal to low
  • summary changed from readwrite002.exe: readwrite002.inout: hWaitForInput: invalid argument (Invalid argument) to Windows: hWaitForInput returns False for file handles
  • milestone changed from 6.6.2 to 6.8

Partial fix:

Thu Aug 30 06:11:15 PDT 2007  Simon Marlow <simonmar@microsoft.com>
  * make hWaitForInput/hReady not fail with "invalid argument" on Windows

Unfortunately inputReady() now returns False for file handles on Windows, and hence neither hReady nor hWaitForInput work properly for file handles on Windows. I'm changing the bug to reflect that.

  Changed 6 years ago by simonmar

  • testcase changed from readwrite002 to readwrite002, hReady001

  Changed 6 years ago by igloo

  • milestone changed from 6.8 branch to _|_

  Changed 5 years ago by simonmar

  • summary changed from Windows: hWaitForInput returns False for file handles to Windows: hWaitForInput returns False for file handles, and doesn't work properly for consoles

I've just spent a while trying to make hReady/hWaitForInput do the right thing for consoles on Windows, and concluded that it basically isn't possible (or at least, I can't find a way to do it).

The problem is that the Windows console tracks all kinds of events, and WaitForMultipleObjects will return true if the console has any pending events, but the trouble is that these events might not be actual characters that can be read (e.g. focus events or key-up events), so when you subsequently call read() on the console it will block. So you can try to filter out all the uninteresting events, but then you have to worry about the fact that e.g. pressing "shift" is a key-down event but doesn't generate a character. At this point I gave up.

So the upshot is that hReady often bogusly returns True for stdin on Windows, in addition to the problems mentioned above with file handles.

follow-up: ↓ 7   Changed 5 years ago by judah

Simon, assuming you're calling ReadConsoleInput to get the console event, I've found the following to work well. An INPUT_RECORD named e corresponds to actual character input when these are all true:

  • e.EventType == KEY_EVENT
  • e.KeyEvent.bKeyDown == TRUE
  • e.KeyEvent.uChar.AsciiChar != '\0'

The third condition filters out modifier keys like "shift".

in reply to: ↑ 6   Changed 5 years ago by simonmar

  • owner set to simonmar
  • milestone changed from _|_ to 6.10.1

Replying to judah:

Simon, assuming you're calling ReadConsoleInput to get the console event, I've found the following to work well. An INPUT_RECORD named e corresponds to actual character input when these are all true: - e.EventType == KEY_EVENT - e.KeyEvent.bKeyDown == TRUE - e.KeyEvent.uChar.AsciiChar != '\0' The third condition filters out modifier keys like "shift".

Interesting, so all I was missing was the third condition. Thanks for that, I'll revive my code and try to get it into GHC 6.10.

Incedentally, since you seem to know a fair bit about the Win32 API, is there a good way to find out whether a given HANDLE corresponds to a console?

  Changed 5 years ago by Deewiant

GetFileType is probably what you want:  http://msdn.microsoft.com/en-us/library/aa364960.aspx

  Changed 5 years ago by simonmar

  • status changed from new to closed
  • resolution set to fixed

Ok, I believe I've fixed this now.

Tue Jul  8 14:42:54 GMT Daylight Time 2008  Simon Marlow <marlowsd@gmail.com>
  * FIX #1198: hWaitForInput on Windows
  Now we do the appropriate magic in fdReady() to detect when there is
  real input available, as opposed to uninteresting console events.

Wed Jul  9 12:10:08 GMT Daylight Time 2008  Simon Marlow <marlowsd@gmail.com>
  * Make threadWaitRead/threadWaitWrite partially useable on Windows

  They work with -threaded by calling fdReady() in a separate thread.

  "threadWaitRead 0" also works without -threaded (because we happen to
  know it's virtually equivalent to "hWaitForInput stdin (-1)").

  Changed 5 years ago by simonmar

  • architecture changed from Unknown to Unknown/Multiple
Note: See TracTickets for help on using tickets.