Debian Bug report logs - #25885
fread() can fail with EINTR !

version graph

Package: libc6; Maintainer for libc6 is GNU Libc Maintainers <debian-glibc@lists.debian.org>; Source for libc6 is src:glibc (PTS, buildd, popcon).

Reported by: Ian Jackson <ijackson@chiark.greenend.org.uk>

Date: Tue, 18 Aug 1998 12:18:03 UTC

Severity: normal

Found in version 2.0.7t-1

Done: Ben Collins <bcollins@debian.org>

Bug is archived. No further changes may be made.

Toggle useless messages

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to debian-bugs-dist@lists.debian.org, Dale Scheetz <dwarf@polaris.net>:
Bug#25885; Package libc6. (full text, mbox, link).


Acknowledgement sent to Ian Jackson <ijackson@chiark.greenend.org.uk>:
New bug report received and forwarded. Copy sent to Dale Scheetz <dwarf@polaris.net>. (full text, mbox, link).


Message #5 received at submit@bugs.debian.org (full text, mbox, reply):

From: Ian Jackson <ijackson@chiark.greenend.org.uk>
To: Debian bugs submission address <submit@bugs.debian.org>
Subject: fread() can fail with EINTR !
Date: Tue, 18 Aug 1998 13:11:23 +0100 (BST)
Package: libc6
Version: 2.0.7t-1

See the transcripts below.  Unfortunately at least in this
incarnation, the bug is intermittent.  However, I could probably
generate a test program to reproduce it.

Thanks,
Ian.

-chiark:~> userv --override execute-from-path ian ls
%backup%~
News
bin
bitmap
core.dpkg-1.4.0.32.2
dead.article
dead.letter
download
dpkg-1.4.0.32.2
emacs
in
junk
keep
letters
lib
mail
mbox
mbox~
out
pgp
private
public-html
things
userv: failure: read error in data: Interrupted system call
-chiark:~> echo $?
255
-chiark:~> dpkg -l userv 'libc6*'
Desired=Unknown/Install/Remove/Purge
| Status=Not/Installed/Config-files/Unpacked/Failed-config/Half-installed
|/ Err?=(none)/Hold/Reinst-required/X=both-problems (Status,Err: uppercase=bad)
||/ Name            Version        Description
+++-===============-==============-============================================
ii  userv           0.58-1.1       `user services' - program call across trust
ii  libc6           2.0.7t-1       The GNU C library version 2 (run-time files)
ii  libc6-dbg       2.0.7t-1       The GNU C library version 2 (debugging/profi
ii  libc6-dev       2.0.7t-1       The GNU C library version 2 (development fil
pn  libc6-doc       <none>         (no description available)
ii  libc6-pic       2.0.7t-1       The GNU C library version 2 (PIC library)
-chiark:~>

chiark:userv-0.58> grep -B 6 -A 2 'read error' *.[ch]
client.c-static void NONRETURNING protoreaderror(FILE *file, const char *where) {
client.c-  int e;
client.c-
client.c-  e= errno;
client.c-  blocksignals(SIG_BLOCK);
client.c-  if (ferror(file)) {
client.c:    fprintf(stderr,"userv: failure: read error %s: %s\n",where,strerror(e));
client.c-  } else {
client.c-    assert(feof(file));
chiark:userv-0.58> egrep -B 3 -A 1 'protoreaderror.*"in data"' *.[ch]
client.c-static void xfread(void *p, size_t sz, FILE *file) {
client.c-  size_t nr;
client.c-  nr= fread(p,1,sz,file);
client.c:  if (nr != sz) protoreaderror(file,"in data");
client.c-}
chiark:userv-0.58>


Information forwarded to debian-bugs-dist@lists.debian.org:
Bug#25885; Package libc6. (full text, mbox, link).


Acknowledgement sent to Dale Scheetz <dwarf@polaris.net>:
Extra info received and forwarded to list. (full text, mbox, link).


Message #10 received at 25885@bugs.debian.org (full text, mbox, reply):

From: Dale Scheetz <dwarf@polaris.net>
To: Ian Jackson <ijackson@chiark.greenend.org.uk>, 25885@bugs.debian.org
Subject: Re: Bug#25885: fread() can fail with EINTR !
Date: Tue, 18 Aug 1998 12:27:21 -0400 (EDT)
Thanks for the report (I think ;-). As this is intermittent, I would ask
several questions:

1. Is there anything special about the file system that this is being
executed upon. Is it an NSF mount for instance, or on a SCSI controler,
or...

2. Is there any file modifying activity going on in this directory when
the ls is executed?

The implication here is that the read process was interupted by another
process. If I understand this correctly that should not happen, although I
am sure that all possible collisions were not considered when the code was
written, so this could be interesting...

Any additional insights would be appreciated.

On Tue, 18 Aug 1998, Ian Jackson wrote:

> Package: libc6
> Version: 2.0.7t-1
> See the transcripts below.  Unfortunately at least in this
> incarnation, the bug is intermittent.  However, I could probably
> generate a test program to reproduce it.
> 
> Thanks,
> Ian.
> 
> -chiark:~> userv --override execute-from-path ian ls
> %backup%~
> News
> bin
> bitmap
> core.dpkg-1.4.0.32.2
> dead.article
> dead.letter
> download
> dpkg-1.4.0.32.2
> emacs
> in
> junk
> keep
> letters
> lib
> mail
> mbox
> mbox~
> out
> pgp
> private
> public-html
> things
> userv: failure: read error in data: Interrupted system call
> -chiark:~> echo $?
> 255
> -chiark:~> dpkg -l userv 'libc6*'
> Desired=Unknown/Install/Remove/Purge
> | Status=Not/Installed/Config-files/Unpacked/Failed-config/Half-installed
> |/ Err?=(none)/Hold/Reinst-required/X=both-problems (Status,Err: uppercase=bad)
> ||/ Name            Version        Description
> +++-===============-==============-============================================
> ii  userv           0.58-1.1       `user services' - program call across trust
> ii  libc6           2.0.7t-1       The GNU C library version 2 (run-time files)
> ii  libc6-dbg       2.0.7t-1       The GNU C library version 2 (debugging/profi
> ii  libc6-dev       2.0.7t-1       The GNU C library version 2 (development fil
> pn  libc6-doc       <none>         (no description available)
> ii  libc6-pic       2.0.7t-1       The GNU C library version 2 (PIC library)
> -chiark:~>
> 
> chiark:userv-0.58> grep -B 6 -A 2 'read error' *.[ch]
> client.c-static void NONRETURNING protoreaderror(FILE *file, const char *where) {
> client.c-  int e;
> client.c-
> client.c-  e= errno;
> client.c-  blocksignals(SIG_BLOCK);
> client.c-  if (ferror(file)) {
> client.c:    fprintf(stderr,"userv: failure: read error %s: %s\n",where,strerror(e));
> client.c-  } else {
> client.c-    assert(feof(file));
> chiark:userv-0.58> egrep -B 3 -A 1 'protoreaderror.*"in data"' *.[ch]
> client.c-static void xfread(void *p, size_t sz, FILE *file) {
> client.c-  size_t nr;
> client.c-  nr= fread(p,1,sz,file);
> client.c:  if (nr != sz) protoreaderror(file,"in data");
> client.c-}
> chiark:userv-0.58>
> 
> 

Dwarf
--
_-_-_-_-_-   Author of "The Debian Linux User's Guide"  _-_-_-_-_-_-

aka   Dale Scheetz                   Phone:   1 (850) 656-9769
      Flexible Software              11000 McCrackin Road
      e-mail:  dwarf@polaris.net     Tallahassee, FL  32308

_-_-_-_-_-_- If you don't see what you want, just ask _-_-_-_-_-_-_-



Information forwarded to debian-bugs-dist@lists.debian.org, Dale Scheetz <dwarf@polaris.net>:
Bug#25885; Package libc6. (full text, mbox, link).


Acknowledgement sent to Ian Jackson <ijackson@chiark.greenend.org.uk>:
Extra info received and forwarded to list. Copy sent to Dale Scheetz <dwarf@polaris.net>. (full text, mbox, link).


Message #15 received at 25885@bugs.debian.org (full text, mbox, reply):

From: Ian Jackson <ijackson@chiark.greenend.org.uk>
To: Dale Scheetz <dwarf@polaris.net>
Cc: 25885@bugs.debian.org
Subject: Re: Bug#25885: fread() can fail with EINTR !
Date: Tue, 18 Aug 1998 19:18:20 +0100 (BST)
Dale Scheetz writes ("Re: Bug#25885: fread() can fail with EINTR !"):
> Thanks for the report (I think ;-). As this is intermittent, I would ask
> several questions:
> 
> 1. Is there anything special about the file system that this is being
> executed upon. Is it an NSF mount for instance, or on a SCSI controler,
> or...

The fd in question is a connected AF_UNIX socket.

> 2. Is there any file modifying activity going on in this directory when
> the ls is executed?

No, the ls was just a command I used to generate some output.

> The implication here is that the read process was interupted by another
> process. If I understand this correctly that should not happen, although I
> am sure that all possible collisions were not considered when the code was
> written, so this could be interesting...

The problem is quite simple, really.

fread(3) calls read(2) to do its work.  read(2) blocks because the
other end of the socket is not writing yet.  Then my process gets a
SIGCHLD, which it handles.  This makes read(2) return EINTR, as
expected.

fread(3) should then retry the read(2).  However, instead, it returns
EINTR to my application and marks the stream as having an error.

To demonstrate more clearly I have produced some transcripts, some on
a libc6 Debian system and some on a libc5 system.

Ian.

/* t.c - sorry, horrible code, full of races and no error checking */

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <signal.h>

static struct sigaction sa;

static void alarmhandler2(int ignored) {
  write(1,"2\n",2);
  _exit(0);
}

static void alarmhandler1(int ignored) {
  int e= errno;
  sa.sa_handler= alarmhandler2;
  sigaction(SIGALRM,&sa,0);
  alarm(2);
  write(1,"1\n",2);
  errno= e;
}

int main(int argc, char **argv) {
  int pipefd[2], r;
  char buf[1];
  FILE *file;

  sa.sa_handler= alarmhandler1;
  sigemptyset(&sa.sa_mask);
  sa.sa_flags= SA_RESETHAND;
  sa.sa_restorer= 0;
  sigaction(SIGALRM,&sa,0);
  
  pipe(pipefd);
  file= fdopen(pipefd[0],"r");
  alarm(2);
  if (argc>1) {
    r= read(pipefd[0],buf,sizeof(buf));
    printf("r=%d e=%s\n",r,strerror(errno));
  } else {
    r= fread(buf,1,sizeof(buf),file);
    printf("r=%d ferror=%d feof=%d e=%s\n",
	   r,ferror(file),feof(file),strerror(errno));
  }
  exit(1);
}


chiark:~/junk> dpkg -l gcc 'libc*-dev' | egrep -v '^.n'
Desired=Unknown/Install/Remove/Purge
| Status=Not/Installed/Config-files/Unpacked/Failed-config/Half-installed
|/ Err?=(none)/Hold/Reinst-required/X=both-problems (Status,Err: uppercase=bad)
||/ Name            Version        Description
+++-===============-==============-============================================
ii  gcc             2.7.2.3-4.8    The GNU C compiler.
ii  libc6-dev       2.0.7t-1       The GNU C library version 2 (development fil
chiark:~/junk> dpkg -l gcc 'libc*-dev' | egrep -v '^.n'
Desired=Unknown/Install/Remove/Purge
| Status=Not/Installed/Config-files/Unpacked/Failed-config/Half-installed
|/ Err?=(none)/Hold/Reinst-required/X=both-problems (Status,Err: uppercase=bad)
||/ Name            Version        Description
+++-===============-==============-============================================
ii  gcc             2.7.2.3-4.8    The GNU C compiler.
ii  libc6-dev       2.0.7t-1       The GNU C library version 2 (development fil
chiark:~/junk> gcc -Wall t.c
chiark:~/junk> strace -o t ./a.out
1
r=0 ferror=1 feof=0 e=Interrupted system call
chiark:~/junk> cat t
execve("./a.out", ["./a.out"], [/* 36 vars */]) = 0
brk(0)                                  = 0x8049b0c
open("/etc/ld.so.preload", O_RDONLY)    = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY)      = 4
fstat(4, {st_mode=0, st_size=0, ...})   = 0
mmap(0, 10971, PROT_READ, MAP_PRIVATE, 4, 0) = 0x4000c000
close(4)                                = 0
open("/lib/libc.so.6", O_RDONLY)        = 4
mmap(0, 4096, PROT_READ, MAP_PRIVATE, 4, 0) = 0x4000f000
munmap(0x4000f000, 4096)                = 0
mmap(0, 673056, PROT_READ|PROT_EXEC, MAP_PRIVATE, 4, 0) = 0x4000f000
mprotect(0x400a1000, 75040, PROT_NONE)  = 0
mmap(0x400a1000, 28672, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 4, 0x91000) = 0x400a1000
mmap(0x400a8000, 46368, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x400a8000
close(4)                                = 0
personality(PER_LINUX)                  = 0
getpid()                                = 10847
sigaction(SIGALRM, {0x8048760, [], SA_STACK|SA_RESTART|SA_INTERRUPT|SA_ONESHOT|SA_NOCLDSTOP|0x7fffd1c}, NULL) = 0
pipe([4, 5])                            = 0
fcntl(4, F_GETFL)                       = 0 (flags O_RDONLY)
brk(0)                                  = 0x8049b0c
brk(0x8049b8c)                          = 0x8049b8c
brk(0x804a000)                          = 0x804a000
fstat(4, {st_mode=0, st_size=0, ...})   = 0
mmap(0, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x400b4000
lseek(4, 0, SEEK_CUR)                   = -1 ESPIPE (Illegal seek)
alarm(2)                                = 0
read(4, 0x400b4000, 4096)               = ? ERESTARTSYS (To be restarted)
--- SIGALRM (Alarm clock) ---
sigaction(SIGALRM, {0x8048730, [], 0}, NULL) = 0
alarm(2)                                = 0
write(1, "1\n", 2)                      = 2
sigreturn()                             = ? (mask now [])
fstat(1, {st_mode=S_ISVTX|0425, st_size=0, ...}) = 0
mmap(0, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x400b5000
ioctl(1, TCGETS, {B38400 opost isig icanon echo ...}) = 0
write(1, "r=0 ferror=1 feof=0 e=Interrupte"..., 46) = 46
munmap(0x400b4000, 4096)                = 0
munmap(0x400b5000, 4096)                = 0
_exit(1)                                = ?
chiark:~/junk>

fowey:~/shared> dpkg -l gcc 'libc*-dev' | egrep -v '^.n'
Desired=Unknown/Install/Remove/Purge
| Status=Not/Installed/Config-files/Unpacked/Failed-config/Half-installed
|/ Err?=(none)/Hold/Reinst-required/X=both-problems (Status,Err: uppercase=bad)
||/ Name            Version        Description
+++-===============-==============-============================================
ii  gcc             2.7.2.1-9      The GNU C compiler (ELF version).
ii  libc5-dev       5.4.33-6       The Linux C library version 5 (development f
fowey:~/shared> gcc -Wall t.c
fowey:~/shared> strace -o t ./a.out
1
2
fowey:~/shared> cat t
execve("./a.out", ["./a.out"], [/* 33 vars */]) = 0
mmap(0, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40007000
mprotect(0x40000000, 20682, PROT_READ|PROT_WRITE|PROT_EXEC) = 0
mprotect(0x8048000, 2344, PROT_READ|PROT_WRITE|PROT_EXEC) = 0
stat("/etc/ld.so.cache", {st_mode=S_IFREG|0644, st_size=4215, ...}) = 0
open("/etc/ld.so.cache", O_RDONLY)      = 4
mmap(0, 4215, PROT_READ, MAP_SHARED, 4, 0) = 0x40008000
close(4)                                = 0
stat("/etc/ld.so.preload", 0xbffffa1c)  = -1 ENOENT (No such file or directory)
open("/lib/libc.so.5", O_RDONLY)        = 4
read(4, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3"..., 4096) = 4096
mmap(0, 765952, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x4000a000
mmap(0x4000a000, 531539, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED, 4, 0) = 0x4000a000
mmap(0x4008c000, 22240, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 4, 0x81000) = 0x4008c000
mmap(0x40092000, 205128, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x40092000
close(4)                                = 0
mprotect(0x4000a000, 531539, PROT_READ|PROT_WRITE|PROT_EXEC) = 0
munmap(0x40008000, 4215)                = 0
mprotect(0x8048000, 2344, PROT_READ|PROT_EXEC) = 0
mprotect(0x4000a000, 531539, PROT_READ|PROT_EXEC) = 0
mprotect(0x40000000, 20682, PROT_READ|PROT_EXEC) = 0
personality(PER_LINUX)                  = 0
geteuid()                               = 516
getuid()                                = 516
getgid()                                = 516
getegid()                               = 516
sigaction(SIGALRM, {0x8048750, [], SA_ONESHOT}, NULL) = 0
pipe([4, 5])                            = 0
fcntl(4, F_GETFL)                       = 0 (flags O_RDONLY)
brk(0x8049a94)                          = 0x8049a94
brk(0x804a000)                          = 0x804a000
fstat(4, {st_mode=S_IFIFO|0600, st_size=0, ...}) = 0
mmap(0, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40008000
lseek(4, 0, SEEK_CUR)                   = -1 ESPIPE (Illegal seek)
alarm(2)                                = 0
read(4, 0x40008000, 4096)               = ? ERESTARTSYS (To be restarted)
--- SIGALRM (Alarm clock) ---
sigaction(SIGALRM, {0x8048720, [], SA_ONESHOT}, NULL) = 0
alarm(2)                                = 0
write(1, "1\n", 2)                      = 2
sigreturn()                             = ? (mask now [])
read(4, 0x40008000, 4096)               = ? ERESTARTSYS (To be restarted)
--- SIGALRM (Alarm clock) ---
write(1, "2\n", 2)                      = 2
_exit(0)                                = ?
fowey:~/shared>


Reply sent to Ben Collins <bcollins@debian.org>:
You have taken responsibility. (full text, mbox, link).


Notification sent to Ian Jackson <ijackson@chiark.greenend.org.uk>:
Bug acknowledged by developer. (full text, mbox, link).


Message #20 received at 25885-done@bugs.debian.org (full text, mbox, reply):

From: Ben Collins <bcollins@debian.org>
To: 25885-done@bugs.debian.org
Subject: review of this bug report
Date: Sun, 7 Jan 2001 17:37:26 -0500
I have reviewed this bug report and am closing it. The basis for my
decision is the reading of the Single Unix Specification (SUSv2), which
reads that return values are that of fgetc(), which specifies this:

    [EINTR]
	The read operation was terminated due to the receipt of a
	signal, and no data was transferred.

Since the function correctly implements the spec, it is not buggy (maybe
you can argue that the spec is buggy, but not that glibc is for
implementing it correctly).

Thanks,
  Ben

-- 
 -----------=======-=-======-=========-----------=====------------=-=------
/  Ben Collins  --  ...on that fantastic voyage...  --  Debian GNU/Linux   \
`  bcollins@debian.org  --  bcollins@openldap.org  --  bcollins@linux.com  '
 `---=========------=======-------------=-=-----=-===-======-------=--=---'



Send a report that this bug log contains spam.


Debian bug tracking system administrator <owner@bugs.debian.org>. Last modified: Fri Apr 19 14:37:52 2024; Machine Name: bembo

Debian Bug tracking system

Debbugs is free software and licensed under the terms of the GNU Public License version 2. The current version can be obtained from https://bugs.debian.org/debbugs-source/.

Copyright © 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson, 2005-2017 Don Armstrong, and many other contributors.