This is the mail archive of the libc-alpha@sources.redhat.com mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

[Various] libc/1828: signal handler chages errno while doing fdopen(3) to pipe.



We've received the appended bug report which I've answered directly
with a reference to ISO C99.

Looking again into it, I noticed that Unix98 and Posix allow to call
certain asynch-signal safe functions - which might set errno as a side
effect.  What can we do?  Can we do anything at all?

Andreas

Subject: Topics

Topics:
   libc/1828: signal handler chages errno while doing fdopen(3) to pipe.
   Re: libc/1828: signal handler chages errno while doing fdopen(3) to pipe.




>Number:         1828
>Category:       libc
>Synopsis:       fdopen(3) to pipe fails
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    libc-gnats
>State:          open
>Class:          sw-bug
>Submitter-Id:   unknown
>Arrival-Date:   Mon Jul 24 05:20:01 EDT 2000
>Last-Modified:
>Originator:     Junjiro Okajima
>Organization:
NEC Informatec Systems Ltd
>Release:        libc-2.1.1 to 2.1.3
>Environment:
	inter celeron, PenII, PenIII, etc.
	linux-2.2.10 to 2.2.16
Host type: i386-pc-linux-gnu
System: Linux nskli014 2.2.16 #2 SMP Fri Jul 14 20:49:35 JST 2000 i686 unknown
Architecture: i686

Addons: crypt linuxthreads localedata
Build CFLAGS: -O2
Build CC: gcc -B$(common-objpfx)
Build shared: yes
Build profile: yes
Build omitfp: no
Stdio: libio

>Description:
	When an application has an event handler which calls some
	systemalls, fdopen(3) to pipe fails somtimes.

	fdopen(3) calls llseek(2) and check the return value and
	errno(global var.) with an internal function file_attach(). If
	the signal handler is called at just after the lseek(), just
	before checking errno, and the signal handler change errno
	other than ESPIPE, fdopen() fails and returns NULL in case of
	lseek() succeeded.

>How-To-Repeat:

/* please adjust a timing parameter to suit your machine */

#include <sys/types.h>
#include <sys/time.h>
#include <sys/times.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <errno.h>
#include <limits.h>
#include <time.h>
#include <fcntl.h>

#define MAGIC 123456789

void
handler(int arg) {
	// if an error happend in systemcall called by me,
	// errno will be updated.
	errno = MAGIC;
}

int
main(int argc, char *argv[])
{
	int ret, fds[2];
	pid_t pid;

	signal(SIGUSR1, handler);
	pid = getpid();

	// send a signal simultaneously
	if (!fork()) {
		struct timespec req;
		unsigned long n = 1;

		req.tv_sec = 0;
		req.tv_nsec = 0;
		ret = 0;
		while (!ret) {
			req.tv_nsec = n++%999;	// adjust here
			nanosleep(&req, NULL);
			ret = kill(pid, SIGUSR1);
		}
		exit(errno);
	}

	ret = pipe(fds);
	if (ret) {
		perror("before test begins");
		exit(errno);
	}
	close(fds[1]);

	{
		struct timespec req;
		unsigned long n = 1;

		req.tv_sec = 0;
		req.tv_nsec = 0;

		while (1) {
			int fd = dup(fds[0]);
			FILE *fp = fdopen(fd, "r");
			if (!fp) {
				perror("Why fdopen");
				signal(SIGUSR1, SIG_DFL);
				kill(-pid, SIGKILL);
				break; // while
			}
			fclose(fp);

			req.tv_nsec = n++%3;	// adjust here
			//nanosleep(&req, NULL);
		}
	}

	kill(-pid, SIGKILL);
	waitpid(-1, NULL, 0);

	return 0;
}

/* end of the code */


>Fix:
	I think it is difficult to fix this bug. This is a matter of
	global variables, and application can check/set errno at
	anytime, but glibc cannot check or depend on errno.
>Audit-Trail:
>Unformatted:






The following reply was made to PR libc/1828; it has been noted by GNATS.

From: Andreas Jaeger <aj@suse.de>
To: Junjiro Okajima <j-okajim@nskli014.nsk.nis.nec.co.jp>
Cc: bugs@gnu.org
Subject: Re: libc/1828: signal handler chages errno while doing fdopen(3) to pipe.
Date: 24 Jul 2000 14:06:55 +0200

 >>>>> Junjiro Okajima writes:
 
 >> Number:         1828
 >> Category:       libc
 >> Synopsis:       fdopen(3) to pipe fails
 >> Confidential:   no
 >> Severity:       serious
 >> Priority:       high
 >> Responsible:    libc-gnats
 >> State:          open
 >> Class:          sw-bug
 >> Submitter-Id:   unknown
 >> Arrival-Date:   Mon Jul 24 05:20:01 EDT 2000
 >> Last-Modified:
 >> Originator:     Junjiro Okajima
 >> Organization:
  > NEC Informatec Systems Ltd
 >> Release:        libc-2.1.1 to 2.1.3
 >> Environment:
  > 	inter celeron, PenII, PenIII, etc.
  > 	linux-2.2.10 to 2.2.16
  > Host type: i386-pc-linux-gnu
  > System: Linux nskli014 2.2.16 #2 SMP Fri Jul 14 20:49:35 JST 2000 i686 unknown
  > Architecture: i686
 
  > Addons: crypt linuxthreads localedata
  > Build CFLAGS: -O2
  > Build CC: gcc -B$(common-objpfx)
  > Build shared: yes
  > Build profile: yes
  > Build omitfp: no
  > Stdio: libio
 
 >> Description:
  > 	When an application has an event handler which calls some
  > 	systemalls, fdopen(3) to pipe fails somtimes.
 
  > 	fdopen(3) calls llseek(2) and check the return value and
  > 	errno(global var.) with an internal function file_attach(). If
  > 	the signal handler is called at just after the lseek(), just
  > 	before checking errno, and the signal handler change errno
  > 	other than ESPIPE, fdopen() fails and returns NULL in case of
  > 	lseek() succeeded.
 
 [...]
 
 
 >> Fix:
  > 	I think it is difficult to fix this bug. This is a matter of
  > 	global variables, and application can check/set errno at
  > 	anytime, but glibc cannot check or depend on errno.
 
 The ISO C standard specifies:
        [#5]  If  the  signal  occurs  other  than  as the result of
        calling  the  abort  or  raise  function,  the  behavior  is
        undefined  if  the  signal handler refers to any object with
        static storage duration other than by assigning a  value  to
        an  object  declared as volatile sig_atomic_t, or the signal
        handler calls any function in  the  standard  library  other
        than  the  abort function, the _Exit function, or the signal
        function with the first argument equal to the signal  number
        corresponding  to  the  signal that caused the invocation of
        the handler.  Furthermore, if such  a  call  to  the  signal
        function  results in a SIG_ERR return, the value of errno is
        indeterminate.211)
 
 Therefore your signal handler is not allowed to mess around with errno
 and call any other functions that might change errno.
 
 Please fix your program.
 
 Andreas
 -- 
  Andreas Jaeger
   SuSE Labs aj@suse.de
    private aj@arthur.inka.de





-- 
 Andreas Jaeger
  SuSE Labs aj@suse.de
   private aj@arthur.inka.de

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]