This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
Re: [Patch] Fix libstdc++/9533
On Tue, Mar 04, 2003 at 10:13:52AM +0100, Paolo Carlini wrote:
> Nathan Myers wrote:
>
> >>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.
>
> Yes.
> I agree that it would be great to avoid the block/no_block
> functions and putting everything inside showmanyc(). On the other
> hand, what I find a little disturbing is that, instead of doing
> this very-low-level work once, during open(), we end up doing it
> repeatedly every time showmanyc() is called. And in general,
> as a general design issue, this kind of code is really special:
> you are not going to find any low-level system call inside the
> other member functions.
> Don't you share with me the feeling that perhaps the problem can
> be fixed (or better avoided completely) by using a new higher
> level strategy, perhaps even involving, a largish redesign of some
> components, I don't know?
IMHO, we should do the least amount of work possible in open(),
and particularly not try to fill a buffer. I know what you mean
about putting lots of low-level operations in a single virtual;
it will get messy with #ifs for stuff that might not be present
on the platform. Still, that is precisely what the virtuals are
for: a place to put detailed semantics. The general stuff is in
basic_streambuf<> members. I expect to see ::write() in overflow()
(only!) and ::read() in underflow() (only!).
> Anyway...
>
> >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.)
>
> Thanks Nathan for this invaluable information. If we all agree to
> actually put this kinf of code inside showmanyc (or better inside a
> __basic_file function called from there, of course) your explanations
> should be largely sufficient for me to prepare something which (almost)
> works.
>
> Two questions, as a check of my understanding:
> 1- You suggest first calling fstat, then, if IFREG or S_IREG are not set,
> calling recv, in order to acquire the similar information for pipes?
I was thinking about this. I now think it would be better to call
::recv() first, and if that fails, call ::fstat. The rationale is
that it is much more likely for it to be called in a loop on a socket,
and ::recv() is a lot cheaper. If the fd is really a file, they
probably only call it once to get the total size and be done.
> 2- After that, we do _not_ actually read the data into the buffer, just
> return from showmanyc a sensible value, a next underflow will do,
> sure to obtain at least that amount of data.
Right.
Nathan Myers
ncm-nospam at cantrip dot org