Still, I think the asynchronous API was the right approach, if just because (as the PA simple API shows) it is possible to implement a synchronous API in terms of it, but not vice versa.
Mandatorily blocking I/O is a curse, even if nonblocking I/O is always trickier to use. Kudos for making the right choice here.