svn commit: r320472 - head/lib/libc/stdio

Konstantin Belousov kib at FreeBSD.org
Thu Jun 29 14:44:22 UTC 2017


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 <sys/types.h>	/* for off_t */
 #include <pthread.h>
 #include <string.h>
@@ -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


More information about the svn-src-head mailing list