From owner-freebsd-threads@FreeBSD.ORG Thu Dec 9 20:30:15 2010 Return-Path: Delivered-To: freebsd-threads@hub.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 7E453106566B for ; Thu, 9 Dec 2010 20:30:15 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:4f8:fff6::28]) by mx1.freebsd.org (Postfix) with ESMTP id 6D3F38FC15 for ; Thu, 9 Dec 2010 20:30:15 +0000 (UTC) Received: from freefall.freebsd.org (localhost [127.0.0.1]) by freefall.freebsd.org (8.14.4/8.14.4) with ESMTP id oB9KUFaX042423 for ; Thu, 9 Dec 2010 20:30:15 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.4/8.14.4/Submit) id oB9KUFTv042418; Thu, 9 Dec 2010 20:30:15 GMT (envelope-from gnats) Date: Thu, 9 Dec 2010 20:30:15 GMT Message-Id: <201012092030.oB9KUFTv042418@freefall.freebsd.org> To: freebsd-threads@FreeBSD.org From: dfilter@FreeBSD.ORG (dfilter service) Cc: Subject: Re: threads/79887: commit references a PR X-BeenThere: freebsd-threads@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: dfilter service List-Id: Threading on FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 09 Dec 2010 20:30:15 -0000 The following reply was made to PR threads/79887; it has been noted by GNATS. From: dfilter@FreeBSD.ORG (dfilter service) To: bug-followup@FreeBSD.org Cc: Subject: Re: threads/79887: commit references a PR Date: Thu, 9 Dec 2010 20:28:37 +0000 (UTC) Author: jhb Date: Thu Dec 9 20:28:30 2010 New Revision: 216334 URL: http://svn.freebsd.org/changeset/base/216334 Log: When reopening a stream backed by an open file descriptor, do not close the existing file descriptor. Instead, let dup2() atomically close the old file descriptor when assigning the newly opened file to the same descriptor. This closes a race in a multithreaded application where a concurrent open() could allocate the existing file descriptor in between the calls to close() and dup2(). PR: threads/79887 Submitted by: Dmitrij Tejblum tejblum of yandex-team.ru Reviewed by: davidxu MFC after: 1 week Modified: head/lib/libc/stdio/freopen.c Modified: head/lib/libc/stdio/freopen.c ============================================================================== --- head/lib/libc/stdio/freopen.c Thu Dec 9 20:16:00 2010 (r216333) +++ head/lib/libc/stdio/freopen.c Thu Dec 9 20:28:30 2010 (r216334) @@ -150,14 +150,6 @@ freopen(file, mode, fp) /* 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: @@ -165,9 +157,11 @@ finish: * Finish closing fp. Even if the open succeeded above, we cannot * keep fp->_base: it may be the wrong size. This loses the effect * of any setbuffer calls, but stdio has always done this before. + * + * Leave the existing file descriptor open until dup2() is called + * below to avoid races where a concurrent open() in another thread + * could claim the existing descriptor. */ - if (isopen) - (void) (*fp->_close)(fp->_cookie); if (fp->_flags & __SMBF) free((char *)fp->_bf._base); fp->_w = 0; @@ -186,6 +180,8 @@ finish: memset(&fp->_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 */ FUNLOCKFILE(fp); errno = sverrno; /* restore in case _close clobbered */ @@ -197,11 +193,12 @@ finish: * 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 + (void)_close(fp->_file); } /* _______________________________________________ svn-src-all@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/svn-src-all To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"