From owner-freebsd-threads@FreeBSD.ORG Wed Apr 13 23:20:27 2005 Return-Path: Delivered-To: freebsd-threads@hub.freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 6056E16A4CE for ; Wed, 13 Apr 2005 23:20:27 +0000 (GMT) Received: from freefall.freebsd.org (freefall.freebsd.org [216.136.204.21]) by mx1.FreeBSD.org (Postfix) with ESMTP id 2837143D2F for ; Wed, 13 Apr 2005 23:20:27 +0000 (GMT) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.13.3/8.13.3) with ESMTP id j3DNKR4U029556 for ; Wed, 13 Apr 2005 23:20:27 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.13.3/8.13.1/Submit) id j3DNKRJ5029553; Wed, 13 Apr 2005 23:20:27 GMT (envelope-from gnats) Resent-Date: Wed, 13 Apr 2005 23:20:27 GMT Resent-Message-Id: <200504132320.j3DNKRJ5029553@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-threads@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, Dmitrij Tejblum Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 345C716A4CE for ; Wed, 13 Apr 2005 23:11:05 +0000 (GMT) Received: from walrus-t.yandex.ru (walrus-t.yandex.ru [213.180.206.233]) by mx1.FreeBSD.org (Postfix) with ESMTP id 4DB1D43D2D for ; Wed, 13 Apr 2005 23:11:04 +0000 (GMT) (envelope-from tejblum@walrus-t.yandex.ru) Received: from walrus-t.yandex.ru (localhost [127.0.0.1]) by walrus-t.yandex.ru (8.13.3/8.13.3) with ESMTP id j3DNB3Ds001478 for ; Thu, 14 Apr 2005 03:11:03 +0400 (MSD) (envelope-from tejblum@walrus-t.yandex.ru) Received: (from tejblum@localhost) by walrus-t.yandex.ru (8.13.3/8.13.3/Submit) id j3DNAxif001464; Thu, 14 Apr 2005 03:10:59 +0400 (MSD) (envelope-from tejblum) Message-Id: <200504132310.j3DNAxif001464@walrus-t.yandex.ru> Date: Thu, 14 Apr 2005 03:10:59 +0400 (MSD) From: Dmitrij Tejblum To: FreeBSD-gnats-submit@FreeBSD.org X-Send-Pr-Version: 3.113 Subject: threads/79887: [patch] freopen() isn't thread-safe X-BeenThere: freebsd-threads@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list Reply-To: Dmitrij Tejblum List-Id: Threading on FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 13 Apr 2005 23:20:27 -0000 >Number: 79887 >Category: threads >Synopsis: [patch] freopen() isn't thread-safe >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-threads >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Wed Apr 13 23:20:26 GMT 2005 >Closed-Date: >Last-Modified: >Originator: Dmitrij Tejblum >Release: FreeBSD 5.4-STABLE i386 >Organization: >Environment: >Description: The freopen() function (1) open the new file, (2) close the old file (3) dup2() the newly opened file to the file descriptor (wantfd) previously held by the old file. (As comments says, "Various C library routines assume stderr is always fd STDERR_FILENO"). So, between step (2) and step (3) the wantfd file descriptor is closed, and if another thread open a file it make take the wantfd descriptor. Then, after the dup2() call in step (3) above, a mess will happen. >How-To-Repeat: >Fix: Don't close the old file descriptor, the dup2() call will do the job. Index: freopen.c =================================================================== RCS file: /home/ncvs/src/lib/libc/stdio/freopen.c,v retrieving revision 1.13 diff -u -r1.13 freopen.c --- freopen.c 22 May 2004 15:19:41 -0000 1.13 +++ freopen.c 13 Apr 2005 22:56:48 -0000 @@ -155,14 +155,6 @@ /* Get a new descriptor to refer to the new file. */ f = _open(file, oflags, DEFFILEMODE); - if (f < 0 && isopen) { - /* If out of fd's close the old one and try again. */ - if (errno == ENFILE || errno == EMFILE) { - (void) (*fp->_close)(fp->_cookie); - isopen = 0; - f = _open(file, oflags, DEFFILEMODE); - } - } sverrno = errno; finish: @@ -171,8 +163,6 @@ * keep fp->_base: it may be the wrong size. This loses the effect * of any setbuffer calls, but stdio has always done this before. */ - if (isopen) - (void) (*fp->_close)(fp->_cookie); if (fp->_flags & __SMBF) free((char *)fp->_bf._base); fp->_w = 0; @@ -191,6 +181,8 @@ memset(&fp->_extra->mbstate, 0, sizeof(mbstate_t)); if (f < 0) { /* did not get it after all */ + if (isopen) + (void) (*fp->_close)(fp->_cookie); fp->_flags = 0; /* set it free */ errno = sverrno; /* restore in case _close clobbered */ FUNLOCKFILE(fp); @@ -202,10 +194,13 @@ * to maintain the descriptor. Various C library routines (perror) * assume stderr is always fd STDERR_FILENO, even if being freopen'd. */ - if (wantfd >= 0 && f != wantfd) { + if (wantfd >= 0) { if (_dup2(f, wantfd) >= 0) { (void)_close(f); f = wantfd; + } else { + if (isopen) + (void) (*fp->_close)(fp->_cookie); } } >Release-Note: >Audit-Trail: >Unformatted: