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