Bug 58768

Summary: The reading file size from a pipe is set to 0 in fstat() of glibc 2.2.4.
Product: [Retired] Red Hat Linux Reporter: Fuchi Hideshi <hfuchi>
Component: kernelAssignee: Arjan van de Ven <arjanv>
Status: CLOSED CURRENTRELEASE QA Contact: Brian Brock <bbrock>
Severity: high Docs Contact:
Priority: medium    
Version: 7.2CC: alan, drepper, naraha_s, rrosario, ynakai
Target Milestone: ---   
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2002-04-30 08:38:20 UTC Type: ---
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Attachments:
Description Flags
This is quick hack of this issue. The difference between old kernel and new one, is only in linux/include/pipe_fs.h, PIPE_LEN(inode). none

Description Fuchi Hideshi 2002-01-24 11:00:24 UTC
From Bugzilla Helper:
User-Agent: Mozilla/5.0 Galeon/1.0.2 (X11; Linux i686; U;) Gecko/20011224

Description of problem:
The reading file size from a pipe is set to 0 in fstat() of glibc 2.2.4.

I was wondering that if you fstat the read end of a pipe, st_size no
longer returns the number of bytes sitting in the buffer.
In this case, glibc 2.2.4 surely returns 0.

The following examinations were performed.
Is this a BUG or proper behavior?


Version-Release number of selected component (if applicable):


How reproducible:
Always

Steps to Reproduce:
1. See following test.
2.
3.
	

Additional info:

-------- test.c -----------

#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/errno.h>

int main( int argc , char *argv[])
{
  struct stat buf;
  if (0 == fstat( fileno(stdin), &buf )) {
    printf( "size %d\n", buf.st_size );   
  } else {
    printf( "size %d\n", buf.st_size );
  }
  exit( 0 );
}

-------- test.c -----------

On Red Hat linux 7.1 with glibc 2.2.2

# gcc test.c
# echo test > test           
# ./a.out < test  
# size 7
# cat test | ./a.out
# size 7

On Red Hat linux 7.1 or 7.2 with glibc 2.2.4

# gcc test.c
# echo test > test           
# ./a.out < test  
# size 7
# cat test | ./a.out
# size 0

Comment 1 Jakub Jelinek 2002-01-24 11:09:28 UTC
This has nothing to do with glibc, it is kernel that fills st_size.

Comment 2 Fuchi Hideshi 2002-01-25 09:33:55 UTC
Well, I tested by upgrading only glibc (version is 2.2.4) to Red Hat
Linux 7.1 just installed. If it does so, this problem did not occur.

Next, I updated kernel (kernel version is 2.4.9-12). The problem occurred.

Please teach me the solution method.


Comment 3 Shinya Narahara 2002-02-13 00:43:44 UTC
Created attachment 45479 [details]
This is quick hack of this issue. The difference between old kernel and new one, is only in linux/include/pipe_fs.h, PIPE_LEN(inode).

Comment 4 Alan Cox 2002-02-13 01:13:48 UTC
Yes - its a kernel happening. However its just luck it ever worked before. The
standards say that i_size is undefined for a pipe. The value 2.4.old used was
not always accurate, and with zero copy pipes in the future its going to be
basically impossible to duplicate this behaviour.

Really you need to fix the code up. For 2.4 there are good reasons to try and
put the compatibility back for people which will hopefully occur in a future
kernel errata (but no guarantee). After 2.4 all bets are off however.



Comment 5 Arjan van de Ven 2002-02-13 09:19:55 UTC
This hack is dangerous.... setting i_size has on-disk concequences.......

Comment 6 Shinya Narahara 2002-03-05 06:09:48 UTC
This seems to be fixed on kernel-2.4.9-31, to add 2 lines patch to linux/fs/stat.c,
however I'm not sure if this is nice method...


Comment 7 Arjan van de Ven 2002-03-05 08:31:41 UTC
The patch for this is 1889 lines (there was quite a bit of infrastructure work
needed for the "2 lines" to be possible). And indeed it's a hack. And yes this
will go away in the future. NOTHING specifies what the value of stat should
return, and once zero-copy pipes are implemented it'll go away again. Please fix
all your applications that depend on this

Comment 8 Arjan van de Ven 2002-03-05 08:32:04 UTC
The patch for this is 1889 lines (there was quite a bit of infrastructure work
needed for the "2 lines" to be possible). And indeed it's a hack. And yes this
will go away in the future. NOTHING specifies what the value of stat should
return, and once zero-copy pipes are implemented it'll go away again. Please fix
all your applications that depend on this

Comment 9 Shinya Narahara 2002-03-06 01:08:37 UTC
As you know, if we don't have any source codes of applications we use(it is binary),
we can't change them not to confirm the pipe size by using fstat(). To use them for
a long time, this fix shouldn't go away, however POSIX doesn't specify it.

AFAIK, there are many unix(s) have this feature, solaris, HP-UX, AIX etc. and
many applications work on them by using one. If Linux doesn't have this,
it may be trouble to port them into Linux without any changes of their sources.


Comment 10 Alan Cox 2002-03-06 01:32:45 UTC
In the long term things like zerocopy pipes mean that the whole question itself
becomes meaningless. Obviously we'll do what we can to keep that - its not our
desire to break stuff.


Comment 11 Nakai 2002-03-06 01:57:52 UTC
Summoning Uli for discussion...

Comment 12 Ulrich Drepper 2002-03-06 02:45:12 UTC
I don't know what you expect to hear from me.  Any program which relies on
unspecified behavior is non-conforming.  Non-conforming programs cannot expect
to be unaffected by system changes.  A feature is left unspecified if either no
concensus about the behavior can be found or, as in this case, it would
over-specify the implementation and prevent future development.  Implementations
will not break unspecified behavior without reason but if it happens and this
causes problems its entirely the application's fault.

Comment 13 Nakai 2002-04-30 08:27:58 UTC
Reopen this bug - won't fix in errata.

Comment 14 Arjan van de Ven 2002-04-30 08:38:15 UTC
Excuse me ?

Comment 15 Nakai 2002-04-30 08:41:03 UTC
After internal discussion, we decided we'll not fix or support this bug
in our Red Hat Linux.

- It's not disclaimed by POSIX. (We do not agree 100% POSIX, though)
- Linux kernel rejects all backward compatibility in its history
  even if application needs lots of fixes to follow up.

This should be marked as WONTFIX

Comment 16 Arjan van de Ven 2002-04-30 08:44:25 UTC
- Linux kernel rejects all backward compatibility in its history
   even if application needs lots of fixes to follow up.

Ehm if we're going to insult eachother here:
The Linux kernel provides FULL backwards compatibility to defined behavior.
It however does not and cannot provide compatibility to undefined behavior since
it's exactly that, undefined. There's no idea what is a valid value in this
case, so returning *any* value is like reading tealeaves about what each
individual application expects.

Comment 17 Arjan van de Ven 2002-04-30 08:53:57 UTC
 But POSIX clearly says:

in fstat(3):
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[...]

The buf argument is a pointer to a stat structure, as defined in
<sys/stat.h>, into which information is placed concerning the file.

[...]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

and in <sys/stat.h>:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[...]

  off_t st_size    For regular files, the file size in bytes
                   For symbolic links, the length in bytes of the
                   pathname contained in the symbolic link.

[...]

Unless otherwise specified, the structure members st_mode, st_ino,
st_dev, st_uid, st_gid, st_atime, st_ctime, and st_mtime shall have
meaningful values for all file types defined in IEEE Std 1003.1-2001.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

This means that the value of the st_size after a call to fstat() on
the descriptor associated with a FIFO is undefined.  Any program
relying on a specific behavior is broken.