id,summary,reporter,owner,description,type,status,milestone,component,version,severity,resolution,keywords,cc 3307,Stream descriptor blocking state set on close,prez@…,chris_kohlhoff,"Say you have the following situation: class A { asio::posix::stream_descriptor stdin; public: A() : stdin(svc, dup(STDIN_FILENO)) { stdin.async_read_some(..., &A::read); } void read() { // do something stdin.async_read_some(..., &A::read); } } A *obj; void read() { obj = new A; } void foo() { asio::posix::stream_descriptor stdin(dup(STDIN_FILENO)); stdin.async_read_some(..., &read) while (!obj) sleep(1); } In this case, a stream descriptor is created from a dup(STDIN_FILENO) twice (assume there are technical reasons why the original stream_descriptor cannot be passed through). So the following happens: stdin constructed stdin - data read async request (set non-blocking) stdin - data read A constructed (A::stdin constructed) A::stdin - data read async request (set non-blocking) stdin destroyed (set blocking) A::stdin - data read A::stdin - data read async request (BLOCKS!) The problem here is that all dups of a file handle share blocking state, and three things are happening in the above. 1. A::stdin is ASSUMED to be blocking when constructed (current blocking state is not checked). This is not a problem, but if I had tried to do a sync read/write, it would have been. 2. Blocking state is maintained by an internal flag, so once the FD has been set non-blocking it does not try to set it non-blocking again. But worse, there is no way to 'override' this if you know for a fact that the descriptor has been set blocking out of ASIO's control. Even stream_descriptor::command with non_blocking_io just sets a flag, rather than doing an actual operation. 3. For no apparent reason, a descriptor that ASIO knows was set non-blocking, gets set back to blocking in close() or destroy(). There is no apparent reason for this really, if the FD is about to be closed, it does not matter what it's blocking state is doing so. I can work around this by manually calling ioctl on A::stdin.native() in the first invocation of A::read(), however this is a hack, and only required because of #2 above.",Bugs,closed,Boost 1.40.0,asio,Boost Development Trunk,Problem,fixed,,