[Patch] Fix libstdc++/9533
Nathan Myers
ncm-nospam@cantrip.org
Mon Mar 3 22:32:00 GMT 2003
On Mon, Mar 03, 2003 at 09:37:31PM +0100, Paolo Carlini wrote:
> Nathan Myers wrote:
>
> >On Mon, Mar 03, 2003 at 07:27:14PM +0100, Paolo Carlini wrote:
> > > ...
> >
> >This looks incomplete to me. I would expect the if statement to be
> >in the #if block. (Likewise in block().)
> >
> Ok. However, when the #if is false, things are quite broken anyway,
> but we have to keep this possibility open (Danny Smith introduced the
> #if def)
>
> > Also, I would expect to
> >see (O_NONBLOCK | __fdflags) passed to fcntl.
> >
> Does it make a difference? I adapted the whole scheme from an example
> somewhere ;) and fcntl(this->fd(), F_SETFL, O_NONBLOCK); was already
> in the code, instead.
The other flags that might be set (and which would be cleared here)
are O_APPEND, O_ASYNC, and any OS-local extensions.
> > fcntl should be called as
> >::fcntl. (Likewise other system calls. Do we have a policy yet?)
> >
> No, sadly :( I think that if we use ::fcntl here it's the _first_ example
> of the syntax!
>
> >Finally, mustn't these members' names be uglified, e.g. _M_no_block
> >etc.?
> >
> The other members of __basic_file<char> aren't and I followed the
> existing practice. Should we change all of them?
Oops, sorry, I confused myself for just long enough to post.
> >It's not clear to me why the non-blocking read is needed at all,
> >
> Honestly, it's not completely clear to me too.
> One thing is sure: the testcase which I posted earlier today breaks
> otherwise:
>
> http://gcc.gnu.org/ml/libstdc++/2003-03/msg00008.html
>
> And 9533 testcase doesn't display the prompt at all.
>
> >or why we're reading on open. Why not wait to read until somebody
> >wants to see some bytes, and just leave the buffer empty until then?
> >(Apologies if this has been discussed at length already.)
> >
> Perhaps it has been discussed before but I appreciate having your
> authoritative opinion.
>
> I *think* that basically Benjamin wanted an in_avail called right
> after the open of a non empty file to return a value != zero.
> If we agree that this is a good thing (I think so) then showmanyc()
> could do the trick, as suggested by P?tur.
>
> Do you agree?
Yes, showmanyc() would be the correct place for it.
> The current showmanyc() is really simple:
> ...
> Dunno what can be put in it according to the standard.
Almost anything. This is good, because now we don't need the
block() and no_block() functions; it all goes in showmanyc().
showmanyc() is supposed to tell all it can find out about how
many bytes are really there, not just how many it has buffered
or will buffer, but it shouldn't take too long about it.
Ideally showmanyc() should try to do an fstat64() on the file
descriptor and report the result, if any. If it's not a file,
then the IFREG or S_ISREG flag won't be set, and the st_size
isn't meaningful. (If fstat64() reports more bytes than a
streamsize could represent, it ought to return
numeric_limits<streamsize>::max(). (Of course there might not
be an fstat64(), so that would have to be #ifdef'ed, and use
fstat() then.))
It also ought to try
::recv(this->fd(), 0, 0, (MSG_DONTWAIT|MSG_PEEK|MSG_NOSIGNAL))
in case it's a socket or pipe. In fact, it should prefer that
over setting and clearing flags on the file descriptor and calling
underflow. It would be rude for showmanyc to actually read the bytes
when it doesn't have to. (If it returns -1, then errno is set to
EAGAIN if it meant to return zero.)
Assuming that fstat and recv don't work, and we decide to try an
underflow, we have an additional complication: suppose the user
sets O_NONBLOCK on the file descriptor himself? We don't want
to clear it. So, we save the original flags value and just
restore them instead of masking O_NONBLOCK out.
int __fdflags = ::fcntl(this->fd(), F_SETFL, O_NONBLOCK);
::fcntl(this->fd(), F_SETFL, (__flags|O_NONBLOCK));
// try to fill a buffer
::fcntl(this->fd(), F_SETFL, __flags);
One danger of actually reading is that if the socket is broken, it
might trigger a SIGPIPE, which we can't afford to catch or ignore.
So I vote for not calling underflow at all, and (thus) not setting
O_NONBLOCK either. I.e. if fstat and recv both fail, then return 0
or -1. (-1 implies we know underflow() would fail. Don't forget
that pending characters in the buffer keep underflow from failing
even the socket itself is broken.)
Nathan Myers
ncm-nospam@cantrip.org
More information about the Libstdc++
mailing list