I/O manager: relying solely upon kqueue is not a safe way to go

Kazu Yamamoto ( 山本和彦 ) kazu at iij.ad.jp
Sat Mar 16 08:57:47 CET 2013

Hello PHO,

First of all, thank you for your hard work! Your test program is
really useful for me.

> 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
> ghci:

I'm building GHC head everyday on Linux, Mac and FreeBSD because I'm
in charge of the parallel IO manager. And I suspect that instability
of building GHC head on Mac is due to the parallel IO manager and
a broken implementation of pipe on Mac.

I know four issues on Mac:

1) http://hackage.haskell.org/trac/ghc/ticket/7651

   GHC head already includes a workaround on this. I guess you know
   this because you are watching this ticket.

2) Building failure on my Mac

3) Instability of "ghc-stage2 --interactive" on your Mac.

4) http://hackage.haskell.org/trac/ghc/ticket/7715

> 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?

I guess your MacOS is too old. My Mac is 10.8.3 whose kevent() does
support tty:

% ./kqueue-poll-select 
Type of stdin: tty

Checking if kqueue(2) works...
Great. kevent(2) successfully handled your stdin.

Checking if poll(2) works...
Good. poll(2) successfully handled your stdin.

Checking if select(2) works...
OK. select(2) successfully handled your stdin.

So, I guess this is not the source of bug 1) and 2).

> 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. 

/dev/random is not supported yet.

./kqueue-poll-select < /dev/random 
Type of stdin: device

Checking if kqueue(2) works...
kevent(2) ifself succeeded but delivered us an EV_ERROR. This is how the old I/O manager was fooled because it wasn't (and the newer one still don't) check this situation: Invalid argument
kevent(2) expectedly failed now. This time we didn't pass a non-NULL incoming event buffer. This is how the new I/O manager fails on this platform.: Invalid argument

Checking if poll(2) works...
poll(2) itself succeeded but delivered us a POLLNVAL event. It can't handle your stdin.

Checking if select(2) works...
OK. select(2) successfully handled your stdin.

> FreeBSD 8.0 does support tty but not /dev/random. I don't know what
> about the latest FreeBSD 9.1:
> https://gist.github.com/phonohawk/5169980#file-i386-unknown-freebsd8-0-txt

According to my test, FreeBSD 9.0 behaves the same.

> 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
> "threadWaitWrite".

I would like to simplify this rule. What about this?

- KQueue/EPoll       -- sockets only
- Select on Mac/Poll -- other things


More information about the ghc-devs mailing list