I/O manager: relying solely upon kqueue is not a safe way to go
andreas.voellmy at gmail.com
Fri Mar 15 23:05:04 CET 2013
Thanks for the detailed message. I will look at your report closely and get
back to you soon.
On Fri, Mar 15, 2013 at 4:20 PM, Johan Tibell <johan.tibell at gmail.com>wrote:
> First, thanks for the very detailed investigation. I've CC:ed Andreas and
> Kazu who has the most knowledge of the I/O manager nowadays.
> -- Johan
> On Fri, Mar 15, 2013 at 12:54 PM, PHO <pho at cielonegro.org> wrote:
>> I found the HEAD stopped working on MacOS X 10.5.8 since the parallel
>> I/O manager got merged to HEAD. Stage-2 compiler successfully builds
>> (including Language.Haskell.TH.Syntax contrary to the report by Kazu
>> Yamamoto) but the resulting binary is very unstable especially for
>> % inplace/bin/ghc-stage2 --interactive
>> GHCi, version 7.7.20130313: http://www.haskell.org/ghc/ :? for help
>> Loading package ghc-prim ... linking ... done.
>> Loading package integer-gmp ... linking ... done.
>> Loading package base ... linking ... done.
>> <stdin>: hGetChar: failed (Operation not supported)
>> So I took a dtruss log and found it was kevent(2) that returned
>> ENOTSUP. GHC.Event.KQueue was just registering the stdin for
>> EVFILT_READ, whose type was of course tty, and then kevent(2) said
>> "tty is not supported". Didn't the old I/O manager do the same thing?
>> Why was it working then?
>> After a hard investigation, I concluded that the old I/O manager was
>> not really working. It just looked fine but in fact wasn't. Here's an
>> explanation: If a fd to be registered is unsupported by kqueue,
>> kevent(2) returns -1 iff no incoming event buffer is passed
>> together. Otherwise it successfully returns with an incoming kevent
>> whose "flags" is EV_ERROR and "data" contains an errno. The I/O
>> manager has always been passing a non-empty event buffer until the
>> commit e5f5cfcd, while it wasn't (and still isn't) checking if a
>> received event in fact represents an error. That is, the KQueue
>> backend asks the kernel to monitor the stdin's readability. The kernel
>> then immediately delivers an event saying ENOTSUP. The KQueue backend
>> thinks "Hey, the stdin is now readable!" so it invokes a callback
>> associated with the fd. The thread which called "threadWaitRead" is
>> now awakened and performs a supposedly non-blocking read on the fd,
>> which in fact blocks but works anyway.
>> However the situation has changed since the commit e5f5cfcd. The I/O
>> manager now registers fds without passing an incoming event buffer, so
>> kevent(2) no longer successfully delivers an error event instead it
>> directly returns -1 with errno set to ENOTSUP, hence the "Operation
>> not supported" exception.
>> The Darwin's kqueue has started supporting tty since MacOS X 10.7
>> (Lion), but I heard it still doesn't support some important devices
>> like /dev/random. FreeBSD's kqueue has some difficulties too. It's no
>> doubt kqueue is a great mechanism for sockets, but IMHO it's not
>> something to use for all kinds of file I/O. Should we then try
>> kqueue(2) first and fallback to poll(2) if failed? Sadly no. Darwin's
>> poll(2) is broken too, and select(2) is the only method reliable:
>> I wrote a small program to test if a given stdin is supported by
>> kqueue, poll and select:
>> MacOS X 10.5.8 is hopelessly broken. We can't use anything other than
>> select(2) for tty and other devices:
>> FreeBSD 8.0 does support tty but not /dev/random. I don't know what
>> about the latest FreeBSD 9.1:
>> NetBSD 6.99.17 works perfectly here:
>> Just for reference, Linux 2.6.16 surely doesn't have kqueue(2) but it
>> supports poll(2)ing on devices:
>> I accordingly suggest that we should have some means to run two
>> independent I/O managers on BSD-like systems: KQueue for sockets,
>> pipes and regular file reads, and Select for any other devices and
>> regular file writes. Note also that no implementations of kqueue
>> support monitoring writability of regular file writes, which also
>> endangers the current use of kqueue-based I/O manager namely
>> Any ideas?
>> - PHO - http://cielonegro.org/
>> OpenPGP public key: 1024D/1A86EF72
>> Fpr: 5F3E 5B5F 535C CE27 8254 4D1A 14E7 9CA7 1A86 EF72
>> ghc-devs mailing list
>> ghc-devs at haskell.org
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the ghc-devs