[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