When you say:
- The way it handles cancellation is not ideal - it should wait until both async operations finish before returning or throwing the relevant exception.
which operations are you referring on? Read and Write?
When you call TimeoutSerial::read, two async operations are fired in parallel: - A read operation (asio::async_read, in your case): https://github.com/fedetft/serial-port/blob/291a7997a665a52bf37d15c615679445... - A timer wait (https://github.com/fedetft/serial-port/blob/291a7997a665a52bf37d15c615679445...) The idea is that you run both in parallel, and when the first one finishes, the second one gets cancelled. However, even if you cancel an Asio async operation, its completion handler gets called (with a cancelled error code). The problem is that TimeoutSerial::read, upon timeout, is cancelling the asio::async_read operation but not waiting for the handler to be called: https://github.com/fedetft/serial-port/blob/291a7997a665a52bf37d15c615679445... This is being workarounded in these lines, but the workaround is not taking OSX into account: https://github.com/fedetft/serial-port/blob/291a7997a665a52bf37d15c615679445... Writing this cleanly requires a big refactor of the class. For a quick workaround, you can try adding this line just after the ones I linked to: if (error == boost::asio::error::operation_aborted) return; Ruben.