Hello, In my (still unreleased) usb-1.0 (https://github.com/basvandijk/usb) library I use the GHC event manager for managing events from the underlying `libusb` C library.
To work with the library a user has to initialize it using: newCtx ∷ IO Ctx The `Ctx` then allows the user to see the USB devices attached to the system using: getDevices ∷ Ctx → IO [Device] From thereon a user can open devices using: openDevice ∷ Device → IO DeviceHandle and perform IO with them: readBulk ∷ DeviceHandle → EndpointAddress → Size → Timeout → IO (B.ByteString, Status) Internally the synchronous `readBulk` is implemented using asynchronous IO: first a request to read bytes from a USB device is asynchronously submitted. Then it waits on a lock (`takeMVar lock`). When the bytes are read an event is fired on a certain file descriptor. The GHC event manager then wakes up and calls a callback which will release the lock (`putMVar lock ()`). I choose to have one event loop per session (`Ctx`) with the usb library. This means that I make a new `EventManager` in `newCtx`: evtMgr ← EventManager.new register the `libusb` file descriptors with the event manager and fork a thread which will `loop` the `EventManager`: tid <- forkIOWithUnmask $ \unmask → unmask $ EventManager.loop evtMgr The underlying `libusb` C library needs to be deinitialized when you're done with it. However for safety and ease of use a user of my Haskell library doesn't need to explicitly deinitialize the library. Instead this happens automatically when the garbage collector collects an unreferenced `Ctx` by registering (using `Foreign.Concurrent.newForeignPtr`) the following finalizer with the `Ctx` foreign pointer: -- Stop the event handling loop by killing its thread: killThread tid ... -- Finally deinitialize libusb: c'libusb_exit ctxPtr As you see I also kill the thread which is running the event manager loop. However I think this is not the right way to do it because when I use the library I see the following message being continually printed after the `Ctx` is finalized: ghc: ioManagerWakeup: write: Bad file descriptor Note that when I remove the `killThread tid` the messages disappear. It seems that killing the event manager loop is not allowed. Is there another way of shutting down the event manager loop? I know I can shut it down by using the `shutdown` function. However this function is asynchronous. This won't work because I need to make sure the event loop is shutdown before I exit the `libusb` library (because that will close the file descriptors that the event loop is working with). I see the event manager provides the `finished` function which will poll the manager to see if it stopped looping. This function is not exported however. Is it possible to export this function? It would be even nicer to have a synchronous shutdown function so that I don't need to setup a loop that waits till the manager has been shut down. Regards, Bas _______________________________________________ Glasgow-haskell-users mailing list Glasgow-haskell-users@haskell.org http://www.haskell.org/mailman/listinfo/glasgow-haskell-users