[Boost-bugs] [Boost C++ Libraries] #3307: Stream descriptor blocking state set on close

Subject: [Boost-bugs] [Boost C++ Libraries] #3307: Stream descriptor blocking state set on close
From: Boost C++ Libraries (noreply_at_[hidden])
Date: 2009-07-31 15:06:22


#3307: Stream descriptor blocking state set on close
-------------------------------------+--------------------------------------
 Reporter: prez@… | Owner: chris_kohlhoff
     Type: Bugs | Status: new
Milestone: Boost 1.40.0 | Component: asio
  Version: Boost Development Trunk | Severity: Problem
 Keywords: |
-------------------------------------+--------------------------------------
 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.

-- 
Ticket URL: <https://svn.boost.org/trac/boost/ticket/3307>
Boost C++ Libraries <http://www.boost.org/>
Boost provides free peer-reviewed portable C++ source libraries.

This archive was generated by hypermail 2.1.7 : 2017-02-16 18:50:00 UTC