From owner-freebsd-bugs@FreeBSD.ORG Tue Jan 18 09:50:24 2005 Return-Path: Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id E904D16A4CE for ; Tue, 18 Jan 2005 09:50:24 +0000 (GMT) Received: from freefall.freebsd.org (freefall.freebsd.org [216.136.204.21]) by mx1.FreeBSD.org (Postfix) with ESMTP id B553F43D53 for ; Tue, 18 Jan 2005 09:50:24 +0000 (GMT) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.13.1/8.13.1) with ESMTP id j0I9oOKJ077462 for ; Tue, 18 Jan 2005 09:50:24 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.13.1/8.13.1/Submit) id j0I9oOER077461; Tue, 18 Jan 2005 09:50:24 GMT (envelope-from gnats) Resent-Date: Tue, 18 Jan 2005 09:50:24 GMT Resent-Message-Id: <200501180950.j0I9oOER077461@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-bugs@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, Yar Tikhiy Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 78DCE16A4CE for ; Tue, 18 Jan 2005 09:49:00 +0000 (GMT) Received: from stylish.chem.msu.su (stylish.chem.msu.su [158.250.32.111]) by mx1.FreeBSD.org (Postfix) with ESMTP id 29FDA43D3F for ; Tue, 18 Jan 2005 09:48:59 +0000 (GMT) (envelope-from yar@stylish.chem.msu.su) Received: from stylish.chem.msu.su (localhost [127.0.0.1]) by stylish.chem.msu.su (8.13.1/8.13.1) with ESMTP id j0I9l1sT033614 for ; Tue, 18 Jan 2005 12:47:01 +0300 (MSK) (envelope-from yar@stylish.chem.msu.su) Received: (from yar@localhost) by stylish.chem.msu.su (8.13.1/8.13.1/Submit) id j0I9l16Y033613; Tue, 18 Jan 2005 12:47:01 +0300 (MSK) (envelope-from yar) Message-Id: <200501180947.j0I9l16Y033613@stylish.chem.msu.su> Date: Tue, 18 Jan 2005 12:47:01 +0300 (MSK) From: Yar Tikhiy To: FreeBSD-gnats-submit@FreeBSD.org X-Send-Pr-Version: 3.113 Subject: bin/76398: stdio can lose data in the presence of signals X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 18 Jan 2005 09:50:25 -0000 >Number: 76398 >Category: bin >Synopsis: stdio can lose data in the presence of signals >Confidential: no >Severity: serious >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Tue Jan 18 09:50:24 GMT 2005 >Closed-Date: >Last-Modified: >Originator: Yar Tikhiy >Release: FreeBSD 6.0-CURRENT i386 >Organization: Moscow State University >Environment: System: FreeBSD stylish.chem.msu.su 6.0-CURRENT FreeBSD 6.0-CURRENT #0: Mon Jan 10 21:00:34 MSK 2005 yar@stylish.chem.msu.su:/usr/obj/usr/src/sys/STYLISH i386 >Description: A signal handler can be installed without the SA_RESTART flag so that the signal will interrupt certain syscalls. The application should be able to restart the interrupted operation by itself if it installs such signal handlers. However, stdio isn't ready for this approach. An interrupted write call will be treated by stdio as an unrecoverable error condition and the current buffer contents will be lost. This is not dictated by the design, but is due to the manner stdio has been coded in. See __sflush() in particular, which is the major source of the problem. >How-To-Repeat: Here's a test program demonstrating the bug easily. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% #include #include #include #include #include #include #include #include #include #include #include #include /* #define CHILD_READER */ /* #define USE_PIPE */ #define NDATA 1000 #define DELAY 2 void hup(int); void setdata(int); char *getdata(void); int main() { char c, digest0[33], digest[33], *p; FILE *fp; int i, s[2]; MD5_CTX md5; pid_t child; struct sigaction sa; MD5Init(&md5); setdata(NDATA); while ((p = getdata())) MD5Update(&md5, p, strlen(p)); p = MD5End(&md5, digest0); printf("True digest is %s\n", digest0); sa.sa_handler = hup; sigemptyset(&sa.sa_mask); sa.sa_flags = 0; if (sigaction(SIGHUP, &sa, NULL) == -1) err(2, "sigaction"); #ifndef USE_PIPE if (socketpair(PF_UNIX, SOCK_STREAM, 0, s) < 0) err(2, "socketpair"); #else if (pipe(s) < 0) err(2, "pipe"); #endif switch (child = fork()) { case -1: err(2, "fork"); #ifndef CHILD_READER case 0: #else default: #endif if ((fp = fdopen(s[0], "w")) == NULL) err(2, "fdopen in writer"); close(s[1]); setdata(NDATA); while ((p = getdata())) for (; *p; p++) if (fputc(*p, fp) == EOF) { if (errno == EINTR) clearerr(fp); else err(2, "fputc"); } fclose(fp); #ifdef CHILD_READER waitpid(child, &i, 0); #endif break; #ifndef CHILD_READER default: #else case 0: #endif close(s[0]); if ((fp = fdopen(s[1], "r")) == NULL) err(2, "fdopen in reader"); sleep(DELAY); #ifndef CHILD_READER if (kill(child, SIGHUP) == -1) #else if (kill(getppid(), SIGHUP) == -1) #endif err(2, "kill"); sleep(DELAY); MD5Init(&md5); while ((i = fgetc(fp)) != EOF) { c = i; MD5Update(&md5, &c, 1); } MD5End(&md5, digest); printf(" Got digest of %s\n", digest); fclose(fp); break; } return (0); } void hup(int signo __unused) { } static int ndata, seq; void setdata(int n) { ndata = n; seq = 0; } char * getdata() { static char databuf[256]; if (seq >= ndata) return (NULL); sprintf(databuf, "%08d xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n", seq++); return (databuf); } %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% >Fix: I'm trying to work one out. >Release-Note: >Audit-Trail: >Unformatted: