From owner-svn-src-head@freebsd.org Thu Jun 29 14:44:22 2017 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 580CDD9F036; Thu, 29 Jun 2017 14:44:22 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 22F2829A6; Thu, 29 Jun 2017 14:44:22 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id v5TEiLbI046424; Thu, 29 Jun 2017 14:44:21 GMT (envelope-from kib@FreeBSD.org) Received: (from kib@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id v5TEiHKR046385; Thu, 29 Jun 2017 14:44:17 GMT (envelope-from kib@FreeBSD.org) Message-Id: <201706291444.v5TEiHKR046385@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: kib set sender to kib@FreeBSD.org using -f From: Konstantin Belousov Date: Thu, 29 Jun 2017 14:44:17 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r320472 - head/lib/libc/stdio X-SVN-Group: head X-SVN-Commit-Author: kib X-SVN-Commit-Paths: head/lib/libc/stdio X-SVN-Commit-Revision: 320472 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 29 Jun 2017 14:44:22 -0000 Author: kib Date: Thu Jun 29 14:44:17 2017 New Revision: 320472 URL: https://svnweb.freebsd.org/changeset/base/320472 Log: Make stdio deferred cancel-safe. If used with fopen(3)/fdopen(3)-ed FILEs, stdio accurately uses non-cancellable internal versions of the functions, i.e. it seems to be fine with regard to cancellation. But if the funopen(3) and f{r,w}open(3) functions were used to open the FILE, and corresponding user functions create cancellation points (they typically have no other choice), then stdio code at least leaks FILE' lock. The change installs cleanup handler which unlocks FILE. Some minimal restructuring of the code was required to make it use common return place to satisfy hand-rolled pthread_cleanup_pop() requirements. Noted by: eugen Reviewed by: eugen, vangyzen Tested by: pho Sponsored by: The FreeBSD Foundation MFC after: 2 weeks Differential revision: https://reviews.freebsd.org/D11246 Modified: head/lib/libc/stdio/fclose.c head/lib/libc/stdio/fflush.c head/lib/libc/stdio/fgetc.c head/lib/libc/stdio/fgetln.c head/lib/libc/stdio/fgets.c head/lib/libc/stdio/fgetwc.c head/lib/libc/stdio/fgetwln.c head/lib/libc/stdio/fgetws.c head/lib/libc/stdio/fputc.c head/lib/libc/stdio/fputs.c head/lib/libc/stdio/fputwc.c head/lib/libc/stdio/fputws.c head/lib/libc/stdio/fread.c head/lib/libc/stdio/freopen.c head/lib/libc/stdio/fscanf.c head/lib/libc/stdio/fseek.c head/lib/libc/stdio/fwrite.c head/lib/libc/stdio/getc.c head/lib/libc/stdio/getchar.c head/lib/libc/stdio/getdelim.c head/lib/libc/stdio/gets.c head/lib/libc/stdio/local.h head/lib/libc/stdio/perror.c head/lib/libc/stdio/putc.c head/lib/libc/stdio/putchar.c head/lib/libc/stdio/puts.c head/lib/libc/stdio/putw.c head/lib/libc/stdio/refill.c head/lib/libc/stdio/scanf.c head/lib/libc/stdio/setvbuf.c head/lib/libc/stdio/stdio.c head/lib/libc/stdio/ungetc.c head/lib/libc/stdio/ungetwc.c head/lib/libc/stdio/vfprintf.c head/lib/libc/stdio/vfscanf.c head/lib/libc/stdio/vfwprintf.c head/lib/libc/stdio/vfwscanf.c head/lib/libc/stdio/vscanf.c Modified: head/lib/libc/stdio/fclose.c ============================================================================== --- head/lib/libc/stdio/fclose.c Thu Jun 29 14:40:33 2017 (r320471) +++ head/lib/libc/stdio/fclose.c Thu Jun 29 14:44:17 2017 (r320472) @@ -97,7 +97,7 @@ fdclose(FILE *fp, int *fdp) return (EOF); } - FLOCKFILE(fp); + FLOCKFILE_CANCELSAFE(fp); r = 0; if (fp->_close != __sclose) { r = EOF; @@ -115,7 +115,7 @@ fdclose(FILE *fp, int *fdp) *fdp = fp->_file; r = cleanfile(fp, false); } - FUNLOCKFILE(fp); + FUNLOCKFILE_CANCELSAFE(); return (r); } @@ -130,9 +130,9 @@ fclose(FILE *fp) return (EOF); } - FLOCKFILE(fp); + FLOCKFILE_CANCELSAFE(fp); r = cleanfile(fp, true); - FUNLOCKFILE(fp); + FUNLOCKFILE_CANCELSAFE(); return (r); } Modified: head/lib/libc/stdio/fflush.c ============================================================================== --- head/lib/libc/stdio/fflush.c Thu Jun 29 14:40:33 2017 (r320471) +++ head/lib/libc/stdio/fflush.c Thu Jun 29 14:44:17 2017 (r320472) @@ -56,7 +56,7 @@ fflush(FILE *fp) if (fp == NULL) return (_fwalk(sflush_locked)); - FLOCKFILE(fp); + FLOCKFILE_CANCELSAFE(fp); /* * There is disagreement about the correct behaviour of fflush() @@ -76,7 +76,7 @@ fflush(FILE *fp) retval = 0; else retval = __sflush(fp); - FUNLOCKFILE(fp); + FUNLOCKFILE_CANCELSAFE(); return (retval); } @@ -143,8 +143,8 @@ sflush_locked(FILE *fp) { int ret; - FLOCKFILE(fp); + FLOCKFILE_CANCELSAFE(fp); ret = __sflush(fp); - FUNLOCKFILE(fp); + FUNLOCKFILE_CANCELSAFE(); return (ret); } Modified: head/lib/libc/stdio/fgetc.c ============================================================================== --- head/lib/libc/stdio/fgetc.c Thu Jun 29 14:40:33 2017 (r320471) +++ head/lib/libc/stdio/fgetc.c Thu Jun 29 14:44:17 2017 (r320472) @@ -46,10 +46,10 @@ int fgetc(FILE *fp) { int retval; - FLOCKFILE(fp); + FLOCKFILE_CANCELSAFE(fp); /* Orientation set by __sgetc() when buffer is empty. */ /* ORIENT(fp, -1); */ retval = __sgetc(fp); - FUNLOCKFILE(fp); + FUNLOCKFILE_CANCELSAFE(); return (retval); } Modified: head/lib/libc/stdio/fgetln.c ============================================================================== --- head/lib/libc/stdio/fgetln.c Thu Jun 29 14:40:33 2017 (r320471) +++ head/lib/libc/stdio/fgetln.c Thu Jun 29 14:44:17 2017 (r320472) @@ -85,22 +85,21 @@ char * fgetln(FILE *fp, size_t *lenp) { unsigned char *p; + char *ret; size_t len; size_t off; - FLOCKFILE(fp); + FLOCKFILE_CANCELSAFE(fp); ORIENT(fp, -1); /* make sure there is input */ if (fp->_r <= 0 && __srefill(fp)) { *lenp = 0; - FUNLOCKFILE(fp); - return (NULL); + ret = NULL; + goto end; } /* look for a newline in the input */ if ((p = memchr((void *)fp->_p, '\n', (size_t)fp->_r)) != NULL) { - char *ret; - /* * Found one. Flag buffer as modified to keep fseek from * `optimising' a backward seek, in case the user stomps on @@ -112,8 +111,7 @@ fgetln(FILE *fp, size_t *lenp) fp->_flags |= __SMOD; fp->_r -= len; fp->_p = p; - FUNLOCKFILE(fp); - return (ret); + goto end; } /* @@ -163,12 +161,14 @@ fgetln(FILE *fp, size_t *lenp) #ifdef notdef fp->_lb._base[len] = '\0'; #endif - FUNLOCKFILE(fp); - return ((char *)fp->_lb._base); + ret = (char *)fp->_lb._base; +end: + FUNLOCKFILE_CANCELSAFE(); + return (ret); error: *lenp = 0; /* ??? */ fp->_flags |= __SERR; - FUNLOCKFILE(fp); - return (NULL); /* ??? */ + ret = NULL; + goto end; } Modified: head/lib/libc/stdio/fgets.c ============================================================================== --- head/lib/libc/stdio/fgets.c Thu Jun 29 14:40:33 2017 (r320471) +++ head/lib/libc/stdio/fgets.c Thu Jun 29 14:44:17 2017 (r320472) @@ -53,17 +53,17 @@ char * fgets(char * __restrict buf, int n, FILE * __restrict fp) { size_t len; - char *s; + char *s, *ret; unsigned char *p, *t; - FLOCKFILE(fp); + FLOCKFILE_CANCELSAFE(fp); ORIENT(fp, -1); if (n <= 0) { /* sanity check */ fp->_flags |= __SERR; errno = EINVAL; - FUNLOCKFILE(fp); - return (NULL); + ret = NULL; + goto end; } s = buf; @@ -76,8 +76,8 @@ fgets(char * __restrict buf, int n, FILE * __restrict if (__srefill(fp)) { /* EOF/error: stop with partial or no line */ if (!__sfeof(fp) || s == buf) { - FUNLOCKFILE(fp); - return (NULL); + ret = NULL; + goto end; } break; } @@ -100,8 +100,8 @@ fgets(char * __restrict buf, int n, FILE * __restrict fp->_p = t; (void)memcpy((void *)s, (void *)p, len); s[len] = 0; - FUNLOCKFILE(fp); - return (buf); + ret = buf; + goto end; } fp->_r -= len; fp->_p += len; @@ -110,6 +110,8 @@ fgets(char * __restrict buf, int n, FILE * __restrict n -= len; } *s = 0; - FUNLOCKFILE(fp); - return (buf); + ret = buf; +end: + FUNLOCKFILE_CANCELSAFE(); + return (ret); } Modified: head/lib/libc/stdio/fgetwc.c ============================================================================== --- head/lib/libc/stdio/fgetwc.c Thu Jun 29 14:40:33 2017 (r320471) +++ head/lib/libc/stdio/fgetwc.c Thu Jun 29 14:44:17 2017 (r320472) @@ -52,10 +52,10 @@ fgetwc_l(FILE *fp, locale_t locale) wint_t r; FIX_LOCALE(locale); - FLOCKFILE(fp); + FLOCKFILE_CANCELSAFE(fp); ORIENT(fp, 1); r = __fgetwc(fp, locale); - FUNLOCKFILE(fp); + FUNLOCKFILE_CANCELSAFE(); return (r); } Modified: head/lib/libc/stdio/fgetwln.c ============================================================================== --- head/lib/libc/stdio/fgetwln.c Thu Jun 29 14:40:33 2017 (r320471) +++ head/lib/libc/stdio/fgetwln.c Thu Jun 29 14:44:17 2017 (r320472) @@ -45,13 +45,14 @@ wchar_t *fgetwln_l(FILE * __restrict, size_t *, locale wchar_t * fgetwln_l(FILE * __restrict fp, size_t *lenp, locale_t locale) { + wchar_t *ret; wint_t wc; size_t len; int savserr; FIX_LOCALE(locale); - FLOCKFILE(fp); + FLOCKFILE_CANCELSAFE(fp); ORIENT(fp, 1); savserr = fp->_flags & __SERR; @@ -77,14 +78,16 @@ fgetwln_l(FILE * __restrict fp, size_t *lenp, locale_t if (len == 0) goto error; - FUNLOCKFILE(fp); *lenp = len; - return ((wchar_t *)fp->_lb._base); + ret = (wchar_t *)fp->_lb._base; +end: + FUNLOCKFILE_CANCELSAFE(); + return (ret); error: - FUNLOCKFILE(fp); *lenp = 0; - return (NULL); + ret = NULL; + goto end; } wchar_t * Modified: head/lib/libc/stdio/fgetws.c ============================================================================== --- head/lib/libc/stdio/fgetws.c Thu Jun 29 14:40:33 2017 (r320471) +++ head/lib/libc/stdio/fgetws.c Thu Jun 29 14:44:17 2017 (r320472) @@ -46,14 +46,14 @@ wchar_t * fgetws_l(wchar_t * __restrict ws, int n, FILE * __restrict fp, locale_t locale) { int sret; - wchar_t *wsp; + wchar_t *wsp, *ret; size_t nconv; const char *src; unsigned char *nl; FIX_LOCALE(locale); struct xlocale_ctype *l = XLOCALE_CTYPE(locale); - FLOCKFILE(fp); + FLOCKFILE_CANCELSAFE(fp); ORIENT(fp, 1); if (n <= 0) { @@ -113,12 +113,14 @@ fgetws_l(wchar_t * __restrict ws, int n, FILE * __rest goto error; ok: *wsp = L'\0'; - FUNLOCKFILE(fp); + ret = ws; +end: + FUNLOCKFILE_CANCELSAFE(); return (ws); error: - FUNLOCKFILE(fp); - return (NULL); + ret = NULL; + goto end; } wchar_t * Modified: head/lib/libc/stdio/fputc.c ============================================================================== --- head/lib/libc/stdio/fputc.c Thu Jun 29 14:40:33 2017 (r320471) +++ head/lib/libc/stdio/fputc.c Thu Jun 29 14:44:17 2017 (r320472) @@ -46,10 +46,10 @@ int fputc(int c, FILE *fp) { int retval; - FLOCKFILE(fp); + FLOCKFILE_CANCELSAFE(fp); /* Orientation set by __sputc() when buffer is full. */ /* ORIENT(fp, -1); */ retval = __sputc(c, fp); - FUNLOCKFILE(fp); + FUNLOCKFILE_CANCELSAFE(); return (retval); } Modified: head/lib/libc/stdio/fputs.c ============================================================================== --- head/lib/libc/stdio/fputs.c Thu Jun 29 14:40:33 2017 (r320471) +++ head/lib/libc/stdio/fputs.c Thu Jun 29 14:44:17 2017 (r320472) @@ -59,10 +59,10 @@ fputs(const char * __restrict s, FILE * __restrict fp) uio.uio_resid = iov.iov_len = strlen(s); uio.uio_iov = &iov; uio.uio_iovcnt = 1; - FLOCKFILE(fp); + FLOCKFILE_CANCELSAFE(fp); ORIENT(fp, -1); retval = __sfvwrite(fp, &uio); - FUNLOCKFILE(fp); + FUNLOCKFILE_CANCELSAFE(); if (retval == 0) return (iov.iov_len > INT_MAX ? INT_MAX : iov.iov_len); return (retval); Modified: head/lib/libc/stdio/fputwc.c ============================================================================== --- head/lib/libc/stdio/fputwc.c Thu Jun 29 14:40:33 2017 (r320471) +++ head/lib/libc/stdio/fputwc.c Thu Jun 29 14:44:17 2017 (r320472) @@ -74,10 +74,10 @@ fputwc_l(wchar_t wc, FILE *fp, locale_t locale) wint_t r; FIX_LOCALE(locale); - FLOCKFILE(fp); + FLOCKFILE_CANCELSAFE(fp); ORIENT(fp, 1); r = __fputwc(wc, fp, locale); - FUNLOCKFILE(fp); + FUNLOCKFILE_CANCELSAFE(); return (r); } Modified: head/lib/libc/stdio/fputws.c ============================================================================== --- head/lib/libc/stdio/fputws.c Thu Jun 29 14:40:33 2017 (r320471) +++ head/lib/libc/stdio/fputws.c Thu Jun 29 14:44:17 2017 (r320472) @@ -53,11 +53,13 @@ fputws_l(const wchar_t * __restrict ws, FILE * __restr const wchar_t *wsp; FIX_LOCALE(locale); struct xlocale_ctype *l = XLOCALE_CTYPE(locale); + int ret; - FLOCKFILE(fp); + ret = -1; + FLOCKFILE_CANCELSAFE(fp); ORIENT(fp, 1); if (prepwrite(fp) != 0) - goto error; + goto end; uio.uio_iov = &iov; uio.uio_iovcnt = 1; iov.iov_base = buf; @@ -66,17 +68,15 @@ fputws_l(const wchar_t * __restrict ws, FILE * __restr nbytes = l->__wcsnrtombs(buf, &wsp, SIZE_T_MAX, sizeof(buf), &fp->_mbstate); if (nbytes == (size_t)-1) - goto error; + goto end; uio.uio_resid = iov.iov_len = nbytes; if (__sfvwrite(fp, &uio) != 0) - goto error; + goto end; } while (wsp != NULL); - FUNLOCKFILE(fp); - return (0); - -error: - FUNLOCKFILE(fp); - return (-1); + ret = 0; +end: + FUNLOCKFILE_CANCELSAFE(); + return (ret); } int Modified: head/lib/libc/stdio/fread.c ============================================================================== --- head/lib/libc/stdio/fread.c Thu Jun 29 14:40:33 2017 (r320471) +++ head/lib/libc/stdio/fread.c Thu Jun 29 14:44:17 2017 (r320472) @@ -54,9 +54,9 @@ fread(void * __restrict buf, size_t size, size_t count { size_t ret; - FLOCKFILE(fp); + FLOCKFILE_CANCELSAFE(fp); ret = __fread(buf, size, count, fp); - FUNLOCKFILE(fp); + FUNLOCKFILE_CANCELSAFE(); return (ret); } Modified: head/lib/libc/stdio/freopen.c ============================================================================== --- head/lib/libc/stdio/freopen.c Thu Jun 29 14:40:33 2017 (r320471) +++ head/lib/libc/stdio/freopen.c Thu Jun 29 14:44:17 2017 (r320472) @@ -68,7 +68,7 @@ freopen(const char * __restrict file, const char * __r return (NULL); } - FLOCKFILE(fp); + FLOCKFILE_CANCELSAFE(fp); if (!__sdidinit) __sinit(); @@ -81,24 +81,24 @@ freopen(const char * __restrict file, const char * __r if (file == NULL) { /* See comment below regarding freopen() of closed files. */ if (fp->_flags == 0) { - FUNLOCKFILE(fp); errno = EINVAL; - return (NULL); + fp = NULL; + goto end; } if ((dflags = _fcntl(fp->_file, F_GETFL)) < 0) { sverrno = errno; fclose(fp); - FUNLOCKFILE(fp); errno = sverrno; - return (NULL); + fp = NULL; + goto end; } /* Work around incorrect O_ACCMODE. */ if ((dflags & O_ACCMODE) != O_RDWR && (dflags & (O_ACCMODE | O_EXEC)) != (oflags & O_ACCMODE)) { fclose(fp); - FUNLOCKFILE(fp); errno = EBADF; - return (NULL); + fp = NULL; + goto end; } if (fp->_flags & __SWR) (void) __sflush(fp); @@ -108,9 +108,9 @@ freopen(const char * __restrict file, const char * __r if (_fcntl(fp->_file, F_SETFL, dflags) < 0) { sverrno = errno; fclose(fp); - FUNLOCKFILE(fp); errno = sverrno; - return (NULL); + fp = NULL; + goto end; } } if (oflags & O_TRUNC) @@ -193,9 +193,9 @@ finish: if (isopen) (void) (*fp->_close)(fp->_cookie); fp->_flags = 0; /* set it free */ - FUNLOCKFILE(fp); errno = sverrno; /* restore in case _close clobbered */ - return (NULL); + fp = NULL; + goto end; } /* @@ -221,9 +221,9 @@ finish: */ if (f > SHRT_MAX) { fp->_flags = 0; /* set it free */ - FUNLOCKFILE(fp); errno = EMFILE; - return (NULL); + fp = NULL; + goto end; } fp->_flags = flags; @@ -245,6 +245,7 @@ finish: fp->_flags2 |= __S2OAP; (void) _sseek(fp, (fpos_t)0, SEEK_END); } - FUNLOCKFILE(fp); +end: + FUNLOCKFILE_CANCELSAFE(); return (fp); } Modified: head/lib/libc/stdio/fscanf.c ============================================================================== --- head/lib/libc/stdio/fscanf.c Thu Jun 29 14:40:33 2017 (r320471) +++ head/lib/libc/stdio/fscanf.c Thu Jun 29 14:44:17 2017 (r320472) @@ -56,10 +56,10 @@ fscanf(FILE * __restrict fp, char const * __restrict f va_list ap; va_start(ap, fmt); - FLOCKFILE(fp); + FLOCKFILE_CANCELSAFE(fp); ret = __svfscanf(fp, __get_locale(), fmt, ap); va_end(ap); - FUNLOCKFILE(fp); + FUNLOCKFILE_CANCELSAFE(); return (ret); } int @@ -70,9 +70,9 @@ fscanf_l(FILE * __restrict fp, locale_t locale, char c FIX_LOCALE(locale); va_start(ap, fmt); - FLOCKFILE(fp); + FLOCKFILE_CANCELSAFE(fp); ret = __svfscanf(fp, locale, fmt, ap); va_end(ap); - FUNLOCKFILE(fp); + FUNLOCKFILE_CANCELSAFE(); return (ret); } Modified: head/lib/libc/stdio/fseek.c ============================================================================== --- head/lib/libc/stdio/fseek.c Thu Jun 29 14:40:33 2017 (r320471) +++ head/lib/libc/stdio/fseek.c Thu Jun 29 14:44:17 2017 (r320472) @@ -60,9 +60,9 @@ fseek(FILE *fp, long offset, int whence) if (!__sdidinit) __sinit(); - FLOCKFILE(fp); + FLOCKFILE_CANCELSAFE(fp); ret = _fseeko(fp, (off_t)offset, whence, 1); - FUNLOCKFILE(fp); + FUNLOCKFILE_CANCELSAFE(); if (ret == 0) errno = serrno; return (ret); @@ -78,9 +78,9 @@ fseeko(FILE *fp, off_t offset, int whence) if (!__sdidinit) __sinit(); - FLOCKFILE(fp); + FLOCKFILE_CANCELSAFE(fp); ret = _fseeko(fp, offset, whence, 0); - FUNLOCKFILE(fp); + FUNLOCKFILE_CANCELSAFE(); if (ret == 0) errno = serrno; return (ret); Modified: head/lib/libc/stdio/fwrite.c ============================================================================== --- head/lib/libc/stdio/fwrite.c Thu Jun 29 14:40:33 2017 (r320471) +++ head/lib/libc/stdio/fwrite.c Thu Jun 29 14:44:17 2017 (r320472) @@ -82,7 +82,7 @@ fwrite(const void * __restrict buf, size_t size, size_ uio.uio_iov = &iov; uio.uio_iovcnt = 1; - FLOCKFILE(fp); + FLOCKFILE_CANCELSAFE(fp); ORIENT(fp, -1); /* * The usual case is success (__sfvwrite returns 0); @@ -91,6 +91,6 @@ fwrite(const void * __restrict buf, size_t size, size_ */ if (__sfvwrite(fp, &uio) != 0) count = (n - uio.uio_resid) / size; - FUNLOCKFILE(fp); + FUNLOCKFILE_CANCELSAFE(); return (count); } Modified: head/lib/libc/stdio/getc.c ============================================================================== --- head/lib/libc/stdio/getc.c Thu Jun 29 14:40:33 2017 (r320471) +++ head/lib/libc/stdio/getc.c Thu Jun 29 14:44:17 2017 (r320472) @@ -49,11 +49,11 @@ int getc(FILE *fp) { int retval; - FLOCKFILE(fp); + FLOCKFILE_CANCELSAFE(fp); /* Orientation set by __sgetc() when buffer is empty. */ /* ORIENT(fp, -1); */ retval = __sgetc(fp); - FUNLOCKFILE(fp); + FUNLOCKFILE_CANCELSAFE(); return (retval); } Modified: head/lib/libc/stdio/getchar.c ============================================================================== --- head/lib/libc/stdio/getchar.c Thu Jun 29 14:40:33 2017 (r320471) +++ head/lib/libc/stdio/getchar.c Thu Jun 29 14:44:17 2017 (r320472) @@ -52,11 +52,11 @@ int getchar(void) { int retval; - FLOCKFILE(stdin); + FLOCKFILE_CANCELSAFE(stdin); /* Orientation set by __sgetc() when buffer is empty. */ /* ORIENT(stdin, -1); */ retval = __sgetc(stdin); - FUNLOCKFILE(stdin); + FUNLOCKFILE_CANCELSAFE(); return (retval); } Modified: head/lib/libc/stdio/getdelim.c ============================================================================== --- head/lib/libc/stdio/getdelim.c Thu Jun 29 14:40:33 2017 (r320471) +++ head/lib/libc/stdio/getdelim.c Thu Jun 29 14:44:17 2017 (r320472) @@ -112,7 +112,7 @@ getdelim(char ** __restrict linep, size_t * __restrict u_char *endp; size_t linelen; - FLOCKFILE(fp); + FLOCKFILE_CANCELSAFE(fp); ORIENT(fp, -1); if (linep == NULL || linecapp == NULL) { @@ -127,9 +127,9 @@ getdelim(char ** __restrict linep, size_t * __restrict /* If fp is at EOF already, we just need space for the NUL. */ if (!__sfeof(fp) || expandtofit(linep, 1, linecapp)) goto error; - FUNLOCKFILE(fp); (*linep)[0] = '\0'; - return (-1); + linelen = -1; + goto end; } linelen = 0; @@ -150,11 +150,12 @@ getdelim(char ** __restrict linep, size_t * __restrict done: /* Invariant: *linep has space for at least linelen+1 bytes. */ (*linep)[linelen] = '\0'; - FUNLOCKFILE(fp); +end: + FUNLOCKFILE_CANCELSAFE(); return (linelen); error: fp->_flags |= __SERR; - FUNLOCKFILE(fp); - return (-1); + linelen = -1; + goto end; } Modified: head/lib/libc/stdio/gets.c ============================================================================== --- head/lib/libc/stdio/gets.c Thu Jun 29 14:40:33 2017 (r320471) +++ head/lib/libc/stdio/gets.c Thu Jun 29 14:44:17 2017 (r320472) @@ -50,27 +50,30 @@ char * gets(char *buf) { int c; - char *s; + char *s, *ret; static int warned; static const char w[] = "warning: this program uses gets(), which is unsafe.\n"; - FLOCKFILE(stdin); + FLOCKFILE_CANCELSAFE(stdin); ORIENT(stdin, -1); if (!warned) { (void) _write(STDERR_FILENO, w, sizeof(w) - 1); warned = 1; } - for (s = buf; (c = __sgetc(stdin)) != '\n';) + for (s = buf; (c = __sgetc(stdin)) != '\n'; ) { if (c == EOF) if (s == buf) { - FUNLOCKFILE(stdin); - return (NULL); + ret = NULL; + goto end; } else break; else *s++ = c; + } *s = 0; - FUNLOCKFILE(stdin); - return (buf); + ret = buf; +end: + FUNLOCKFILE_CANCELSAFE(); + return (ret); } Modified: head/lib/libc/stdio/local.h ============================================================================== --- head/lib/libc/stdio/local.h Thu Jun 29 14:40:33 2017 (r320471) +++ head/lib/libc/stdio/local.h Thu Jun 29 14:44:17 2017 (r320472) @@ -38,6 +38,9 @@ * $FreeBSD$ */ +#ifndef _STDIO_LOCAL_H +#define _STDIO_LOCAL_H + #include /* for off_t */ #include #include @@ -138,3 +141,26 @@ __fgetwc(FILE *fp, locale_t locale) if ((fp)->_orientation == 0) \ (fp)->_orientation = (o); \ } while (0) + +void __stdio_cancel_cleanup(void *); +#define FLOCKFILE_CANCELSAFE(fp) \ + { \ + struct _pthread_cleanup_info __cleanup_info__; \ + if (__isthreaded) { \ + _FLOCKFILE(fp); \ + __pthread_cleanup_push_imp( \ + __stdio_cancel_cleanup, (fp), \ + &__cleanup_info__); \ + } else { \ + __pthread_cleanup_push_imp( \ + __stdio_cancel_cleanup, NULL, \ + &__cleanup_info__); \ + } \ + { +#define FUNLOCKFILE_CANCELSAFE() \ + (void)0; \ + } \ + __pthread_cleanup_pop_imp(1); \ + } + +#endif /* _STDIO_LOCAL_H */ Modified: head/lib/libc/stdio/perror.c ============================================================================== --- head/lib/libc/stdio/perror.c Thu Jun 29 14:40:33 2017 (r320471) +++ head/lib/libc/stdio/perror.c Thu Jun 29 14:44:17 2017 (r320472) @@ -67,9 +67,9 @@ perror(const char *s) v++; v->iov_base = "\n"; v->iov_len = 1; - FLOCKFILE(stderr); + FLOCKFILE_CANCELSAFE(stderr); __sflush(stderr); (void)_writev(stderr->_file, iov, (v - iov) + 1); stderr->_flags &= ~__SOFF; - FUNLOCKFILE(stderr); + FUNLOCKFILE_CANCELSAFE(); } Modified: head/lib/libc/stdio/putc.c ============================================================================== --- head/lib/libc/stdio/putc.c Thu Jun 29 14:40:33 2017 (r320471) +++ head/lib/libc/stdio/putc.c Thu Jun 29 14:44:17 2017 (r320472) @@ -49,11 +49,11 @@ int putc(int c, FILE *fp) { int retval; - FLOCKFILE(fp); + FLOCKFILE_CANCELSAFE(fp); /* Orientation set by __sputc() when buffer is full. */ /* ORIENT(fp, -1); */ retval = __sputc(c, fp); - FUNLOCKFILE(fp); + FUNLOCKFILE_CANCELSAFE(); return (retval); } Modified: head/lib/libc/stdio/putchar.c ============================================================================== --- head/lib/libc/stdio/putchar.c Thu Jun 29 14:40:33 2017 (r320471) +++ head/lib/libc/stdio/putchar.c Thu Jun 29 14:44:17 2017 (r320472) @@ -54,11 +54,11 @@ putchar(int c) int retval; FILE *so = stdout; - FLOCKFILE(so); + FLOCKFILE_CANCELSAFE(so); /* Orientation set by __sputc() when buffer is full. */ /* ORIENT(so, -1); */ retval = __sputc(c, so); - FUNLOCKFILE(so); + FUNLOCKFILE_CANCELSAFE(); return (retval); } Modified: head/lib/libc/stdio/puts.c ============================================================================== --- head/lib/libc/stdio/puts.c Thu Jun 29 14:40:33 2017 (r320471) +++ head/lib/libc/stdio/puts.c Thu Jun 29 14:44:17 2017 (r320472) @@ -62,9 +62,9 @@ puts(char const *s) uio.uio_resid = c + 1; uio.uio_iov = &iov[0]; uio.uio_iovcnt = 2; - FLOCKFILE(stdout); + FLOCKFILE_CANCELSAFE(stdout); ORIENT(stdout, -1); retval = __sfvwrite(stdout, &uio) ? EOF : '\n'; - FUNLOCKFILE(stdout); + FUNLOCKFILE_CANCELSAFE(); return (retval); } Modified: head/lib/libc/stdio/putw.c ============================================================================== --- head/lib/libc/stdio/putw.c Thu Jun 29 14:40:33 2017 (r320471) +++ head/lib/libc/stdio/putw.c Thu Jun 29 14:44:17 2017 (r320472) @@ -41,6 +41,7 @@ __FBSDID("$FreeBSD$"); #include "un-namespace.h" #include "fvwrite.h" #include "libc_private.h" +#include "local.h" int putw(int w, FILE *fp) @@ -53,8 +54,8 @@ putw(int w, FILE *fp) uio.uio_resid = iov.iov_len = sizeof(w); uio.uio_iov = &iov; uio.uio_iovcnt = 1; - FLOCKFILE(fp); + FLOCKFILE_CANCELSAFE(fp); retval = __sfvwrite(fp, &uio); - FUNLOCKFILE(fp); + FUNLOCKFILE_CANCELSAFE(); return (retval); } Modified: head/lib/libc/stdio/refill.c ============================================================================== --- head/lib/libc/stdio/refill.c Thu Jun 29 14:40:33 2017 (r320471) +++ head/lib/libc/stdio/refill.c Thu Jun 29 14:44:17 2017 (r320472) @@ -53,9 +53,9 @@ lflush(FILE *fp) int ret = 0; if ((fp->_flags & (__SLBF|__SWR)) == (__SLBF|__SWR)) { - FLOCKFILE(fp); + FLOCKFILE_CANCELSAFE(fp); ret = __sflush(fp); - FUNLOCKFILE(fp); + FUNLOCKFILE_CANCELSAFE(); } return (ret); } Modified: head/lib/libc/stdio/scanf.c ============================================================================== --- head/lib/libc/stdio/scanf.c Thu Jun 29 14:40:33 2017 (r320471) +++ head/lib/libc/stdio/scanf.c Thu Jun 29 14:44:17 2017 (r320472) @@ -56,9 +56,9 @@ scanf(char const * __restrict fmt, ...) va_list ap; va_start(ap, fmt); - FLOCKFILE(stdin); + FLOCKFILE_CANCELSAFE(stdin); ret = __svfscanf(stdin, __get_locale(), fmt, ap); - FUNLOCKFILE(stdin); + FUNLOCKFILE_CANCELSAFE(); va_end(ap); return (ret); } @@ -70,9 +70,9 @@ scanf_l(locale_t locale, char const * __restrict fmt, FIX_LOCALE(locale); va_start(ap, fmt); - FLOCKFILE(stdin); + FLOCKFILE_CANCELSAFE(stdin); ret = __svfscanf(stdin, locale, fmt, ap); - FUNLOCKFILE(stdin); + FUNLOCKFILE_CANCELSAFE(); va_end(ap); return (ret); } Modified: head/lib/libc/stdio/setvbuf.c ============================================================================== --- head/lib/libc/stdio/setvbuf.c Thu Jun 29 14:40:33 2017 (r320471) +++ head/lib/libc/stdio/setvbuf.c Thu Jun 29 14:44:17 2017 (r320472) @@ -63,7 +63,7 @@ setvbuf(FILE * __restrict fp, char * __restrict buf, i if ((mode != _IOFBF && mode != _IOLBF) || (int)size < 0) return (EOF); - FLOCKFILE(fp); + FLOCKFILE_CANCELSAFE(fp); /* * Write current buffer, if any. Discard unread input (including * ungetc data), cancel line buffering, and free old buffer if @@ -115,8 +115,7 @@ nbf: fp->_w = 0; fp->_bf._base = fp->_p = fp->_nbuf; fp->_bf._size = 1; - FUNLOCKFILE(fp); - return (ret); + goto end; } flags |= __SMBF; } @@ -156,6 +155,7 @@ nbf: } __cleanup = _cleanup; - FUNLOCKFILE(fp); +end: + FUNLOCKFILE_CANCELSAFE(); return (ret); } Modified: head/lib/libc/stdio/stdio.c ============================================================================== --- head/lib/libc/stdio/stdio.c Thu Jun 29 14:40:33 2017 (r320471) +++ head/lib/libc/stdio/stdio.c Thu Jun 29 14:44:17 2017 (r320472) @@ -166,3 +166,11 @@ _sseek(FILE *fp, fpos_t offset, int whence) } return (ret); } + +void +__stdio_cancel_cleanup(void * arg) +{ + + if (arg != NULL) + _funlockfile((FILE *)arg); +} Modified: head/lib/libc/stdio/ungetc.c ============================================================================== --- head/lib/libc/stdio/ungetc.c Thu Jun 29 14:40:33 2017 (r320471) +++ head/lib/libc/stdio/ungetc.c Thu Jun 29 14:44:17 2017 (r320472) @@ -94,10 +94,10 @@ ungetc(int c, FILE *fp) if (!__sdidinit) __sinit(); - FLOCKFILE(fp); + FLOCKFILE_CANCELSAFE(fp); ORIENT(fp, -1); ret = __ungetc(c, fp); - FUNLOCKFILE(fp); + FUNLOCKFILE_CANCELSAFE(); return (ret); } Modified: head/lib/libc/stdio/ungetwc.c ============================================================================== --- head/lib/libc/stdio/ungetwc.c Thu Jun 29 14:40:33 2017 (r320471) +++ head/lib/libc/stdio/ungetwc.c Thu Jun 29 14:44:17 2017 (r320472) @@ -76,10 +76,10 @@ ungetwc_l(wint_t wc, FILE *fp, locale_t locale) wint_t r; FIX_LOCALE(locale); - FLOCKFILE(fp); + FLOCKFILE_CANCELSAFE(fp); ORIENT(fp, 1); r = __ungetwc(wc, fp, locale); - FUNLOCKFILE(fp); + FUNLOCKFILE_CANCELSAFE(); return (r); } Modified: head/lib/libc/stdio/vfprintf.c ============================================================================== --- head/lib/libc/stdio/vfprintf.c Thu Jun 29 14:40:33 2017 (r320471) +++ head/lib/libc/stdio/vfprintf.c Thu Jun 29 14:44:17 2017 (r320472) @@ -274,14 +274,14 @@ vfprintf_l(FILE * __restrict fp, locale_t locale, cons int ret; FIX_LOCALE(locale); - FLOCKFILE(fp); + FLOCKFILE_CANCELSAFE(fp); /* optimise fprintf(stderr) (and other unbuffered Unix files) */ if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) && fp->_file >= 0) ret = __sbprintf(fp, locale, fmt0, ap); else ret = __vfprintf(fp, locale, fmt0, ap); - FUNLOCKFILE(fp); + FUNLOCKFILE_CANCELSAFE(); return (ret); } int Modified: head/lib/libc/stdio/vfscanf.c ============================================================================== --- head/lib/libc/stdio/vfscanf.c Thu Jun 29 14:40:33 2017 (r320471) +++ head/lib/libc/stdio/vfscanf.c Thu Jun 29 14:44:17 2017 (r320472) @@ -443,9 +443,9 @@ __vfscanf(FILE *fp, char const *fmt0, va_list ap) { int ret; - FLOCKFILE(fp); + FLOCKFILE_CANCELSAFE(fp); ret = __svfscanf(fp, __get_locale(), fmt0, ap); - FUNLOCKFILE(fp); + FUNLOCKFILE_CANCELSAFE(); return (ret); } int @@ -454,9 +454,9 @@ vfscanf_l(FILE *fp, locale_t locale, char const *fmt0, int ret; FIX_LOCALE(locale); - FLOCKFILE(fp); + FLOCKFILE_CANCELSAFE(fp); ret = __svfscanf(fp, locale, fmt0, ap); - FUNLOCKFILE(fp); + FUNLOCKFILE_CANCELSAFE(); return (ret); } Modified: head/lib/libc/stdio/vfwprintf.c ============================================================================== --- head/lib/libc/stdio/vfwprintf.c Thu Jun 29 14:40:33 2017 (r320471) +++ head/lib/libc/stdio/vfwprintf.c Thu Jun 29 14:44:17 2017 (r320472) @@ -356,14 +356,14 @@ vfwprintf_l(FILE * __restrict fp, locale_t locale, { int ret; FIX_LOCALE(locale); - FLOCKFILE(fp); + FLOCKFILE_CANCELSAFE(fp); /* optimise fprintf(stderr) (and other unbuffered Unix files) */ if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) && fp->_file >= 0) ret = __sbprintf(fp, locale, fmt0, ap); else ret = __vfwprintf(fp, locale, fmt0, ap); - FUNLOCKFILE(fp); + FUNLOCKFILE_CANCELSAFE(); return (ret); } int Modified: head/lib/libc/stdio/vfwscanf.c ============================================================================== --- head/lib/libc/stdio/vfwscanf.c Thu Jun 29 14:40:33 2017 (r320471) +++ head/lib/libc/stdio/vfwscanf.c Thu Jun 29 14:44:17 2017 (r320472) @@ -428,10 +428,10 @@ vfwscanf_l(FILE * __restrict fp, locale_t locale, int ret; FIX_LOCALE(locale); - FLOCKFILE(fp); + FLOCKFILE_CANCELSAFE(fp); ORIENT(fp, 1); ret = __vfwscanf(fp, locale, fmt, ap); - FUNLOCKFILE(fp); + FUNLOCKFILE_CANCELSAFE(); return (ret); } int Modified: head/lib/libc/stdio/vscanf.c ============================================================================== --- head/lib/libc/stdio/vscanf.c Thu Jun 29 14:40:33 2017 (r320471) +++ head/lib/libc/stdio/vscanf.c Thu Jun 29 14:44:17 2017 (r320472) @@ -54,9 +54,9 @@ vscanf_l(locale_t locale, const char * __restrict fmt, int retval; FIX_LOCALE(locale); - FLOCKFILE(stdin); + FLOCKFILE_CANCELSAFE(stdin); retval = __svfscanf(stdin, locale, fmt, ap); - FUNLOCKFILE(stdin); + FUNLOCKFILE_CANCELSAFE(); return (retval); } int