On Sat, Oct 11, 2014 at 12:17 AM, Ben Gamari <bgamari.foss@gmail.com> wrote:

In ba2555ef and a6f52b19 one-shot semantics were added to event manager
in `base`. If my understanding of this code is correct, in this mode the
event manager will use only notify the user of the first event on a
registered fd after which point the fd will need to be re-registered to
get another notification.

Yes.
 
It appears this was done to optimize the
common case of file I/O where only a single event is needed

Yes.
 

This change lead to a regression[1] in Bas van Dijk's usb library under
GHC 7.8. usb's use of the event manager requires that all events on an
fd are reported until the fd is registered or else hardware events are
lost.

The change should only affect libraries using GHC.Event (or other modules underneath), which are exposed, but considered "internal". I searched hackage before making this change and usb was the only library that came up using GHC.Event directly. I'm not sure if I sent the usb maintainers an email now... I really should have done that to save you the effort of hunting down the problem in usb. 
 

I'm a bit perplexed as to why the change was made in the way that it
was.  Making one-shot a event-manager-wide attribute seems to add a fair
bit of complexity to the subsystem while breaking backwards
compatibility with library code.

It added some complexity to the IO manager, but that should not affect clients except those using the internal interface. 
 
Going forward library authors now need
to worry about whether the system event manager is one-shot or not.

Yes, but only library authors using the internal interface.
 
Not
only is this platform dependent but it seems that there is no way for a
user to determine which semantics the system event handler uses. 

Is there a reason why one-shot wasn't exported as a per-fd attribute
instead of per-manager? Might it be possible to back out this change and
instead add a variant of `registerFd` which exposes one-shot semantics?


The system event manager is configured by GHC.Thread using ONE_SHOT if the system supports it. 

You can always create your own EventManager using GHC.Event.Manager.new or GHC.Event.Manager.newWith functions. Those functions take a Bool argument that control whether ONE_SHOT is used by the Manager returned by that function (False means not to use ONE_SHOT). Would this work for usb? 

-Andi
 
Cheers,

- Ben


[1] https://github.com/basvandijk/usb/issues/7