diff options
Diffstat (limited to 'lib/libc')
39 files changed, 191 insertions, 139 deletions
| diff --git a/lib/libc/include/libc_private.h b/lib/libc/include/libc_private.h index 0f1ed854a6b7..314533fe6cd1 100644 --- a/lib/libc/include/libc_private.h +++ b/lib/libc/include/libc_private.h @@ -405,4 +405,9 @@ void __libc_map_stacks_exec(void);  void	_pthread_cancel_enter(int);  void	_pthread_cancel_leave(int); +struct _pthread_cleanup_info; +void	___pthread_cleanup_push_imp(void (*)(void *), void *, +	    struct _pthread_cleanup_info *); +void	___pthread_cleanup_pop_imp(int); +  #endif /* _LIBC_PRIVATE_H_ */ diff --git a/lib/libc/stdio/fclose.c b/lib/libc/stdio/fclose.c index 24b9b90af985..063ef841f72c 100644 --- a/lib/libc/stdio/fclose.c +++ b/lib/libc/stdio/fclose.c @@ -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);  } diff --git a/lib/libc/stdio/fflush.c b/lib/libc/stdio/fflush.c index 123167a09129..5ecfc4451f67 100644 --- a/lib/libc/stdio/fflush.c +++ b/lib/libc/stdio/fflush.c @@ -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);  } diff --git a/lib/libc/stdio/fgetc.c b/lib/libc/stdio/fgetc.c index 2ee4d7a78cb5..025a0c2df394 100644 --- a/lib/libc/stdio/fgetc.c +++ b/lib/libc/stdio/fgetc.c @@ -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);  } diff --git a/lib/libc/stdio/fgetln.c b/lib/libc/stdio/fgetln.c index c8e30ee2bf65..1e6b9842bcec 100644 --- a/lib/libc/stdio/fgetln.c +++ b/lib/libc/stdio/fgetln.c @@ -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;  } diff --git a/lib/libc/stdio/fgets.c b/lib/libc/stdio/fgets.c index a2e39ed3b337..95d0ad997196 100644 --- a/lib/libc/stdio/fgets.c +++ b/lib/libc/stdio/fgets.c @@ -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 fp)  			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)  			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 fp)  		n -= len;  	}  	*s = 0; -	FUNLOCKFILE(fp); -	return (buf); +	ret = buf; +end: +	FUNLOCKFILE_CANCELSAFE(); +	return (ret);  } diff --git a/lib/libc/stdio/fgetwc.c b/lib/libc/stdio/fgetwc.c index 3074d441f9f6..5f13e2dd4b74 100644 --- a/lib/libc/stdio/fgetwc.c +++ b/lib/libc/stdio/fgetwc.c @@ -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);  } diff --git a/lib/libc/stdio/fgetwln.c b/lib/libc/stdio/fgetwln.c index 037657c224b0..a29f1f6bfb3b 100644 --- a/lib/libc/stdio/fgetwln.c +++ b/lib/libc/stdio/fgetwln.c @@ -45,13 +45,14 @@ wchar_t *fgetwln_l(FILE * __restrict, size_t *, locale_t);  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 locale)  	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 * diff --git a/lib/libc/stdio/fgetws.c b/lib/libc/stdio/fgetws.c index 8513a372835b..f47fea79934d 100644 --- a/lib/libc/stdio/fgetws.c +++ b/lib/libc/stdio/fgetws.c @@ -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 * __restrict fp, locale_t locale)  		goto error;  ok:  	*wsp = L'\0'; -	FUNLOCKFILE(fp); -	return (ws); +	ret = ws; +end: +	FUNLOCKFILE_CANCELSAFE(); +	return (ret);  error: -	FUNLOCKFILE(fp); -	return (NULL); +	ret = NULL; +	goto end;  }  wchar_t * diff --git a/lib/libc/stdio/fputc.c b/lib/libc/stdio/fputc.c index 3b6101f92f4d..32c261aa3685 100644 --- a/lib/libc/stdio/fputc.c +++ b/lib/libc/stdio/fputc.c @@ -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);  } diff --git a/lib/libc/stdio/fputs.c b/lib/libc/stdio/fputs.c index 32e57645f56a..9376af587563 100644 --- a/lib/libc/stdio/fputs.c +++ b/lib/libc/stdio/fputs.c @@ -58,9 +58,9 @@ 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();  	return (retval);  } diff --git a/lib/libc/stdio/fputwc.c b/lib/libc/stdio/fputwc.c index 7f0c9109b087..d16886734335 100644 --- a/lib/libc/stdio/fputwc.c +++ b/lib/libc/stdio/fputwc.c @@ -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);  } diff --git a/lib/libc/stdio/fputws.c b/lib/libc/stdio/fputws.c index 41530673c007..19da946054b7 100644 --- a/lib/libc/stdio/fputws.c +++ b/lib/libc/stdio/fputws.c @@ -53,11 +53,13 @@ fputws_l(const wchar_t * __restrict ws, FILE * __restrict fp, locale_t locale)  	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 * __restrict fp, locale_t locale)  		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 diff --git a/lib/libc/stdio/fread.c b/lib/libc/stdio/fread.c index c24df9914b48..ff1c65b480d8 100644 --- a/lib/libc/stdio/fread.c +++ b/lib/libc/stdio/fread.c @@ -54,9 +54,9 @@ fread(void * __restrict buf, size_t size, size_t count, FILE * __restrict fp)  {  	size_t ret; -	FLOCKFILE(fp); +	FLOCKFILE_CANCELSAFE(fp);  	ret = __fread(buf, size, count, fp); -	FUNLOCKFILE(fp); +	FUNLOCKFILE_CANCELSAFE();  	return (ret);  } diff --git a/lib/libc/stdio/freopen.c b/lib/libc/stdio/freopen.c index e0104c88eef6..3d6cc89b6fa0 100644 --- a/lib/libc/stdio/freopen.c +++ b/lib/libc/stdio/freopen.c @@ -68,7 +68,7 @@ freopen(const char * __restrict file, const char * __restrict mode,  		return (NULL);  	} -	FLOCKFILE(fp); +	FLOCKFILE_CANCELSAFE(fp);  	if (!__sdidinit)  		__sinit(); @@ -81,24 +81,24 @@ freopen(const char * __restrict file, const char * __restrict mode,  	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 * __restrict mode,  			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);  } diff --git a/lib/libc/stdio/fscanf.c b/lib/libc/stdio/fscanf.c index 014f09415048..d3e093334482 100644 --- a/lib/libc/stdio/fscanf.c +++ b/lib/libc/stdio/fscanf.c @@ -56,10 +56,10 @@ fscanf(FILE * __restrict fp, char const * __restrict fmt, ...)  	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 const * __restrict fmt, ...  	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);  } diff --git a/lib/libc/stdio/fseek.c b/lib/libc/stdio/fseek.c index 2897eebf9c88..e933bdabf4d2 100644 --- a/lib/libc/stdio/fseek.c +++ b/lib/libc/stdio/fseek.c @@ -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); diff --git a/lib/libc/stdio/fwrite.c b/lib/libc/stdio/fwrite.c index 5b57fab0b9e1..41bb4f6b0384 100644 --- a/lib/libc/stdio/fwrite.c +++ b/lib/libc/stdio/fwrite.c @@ -82,7 +82,7 @@ fwrite(const void * __restrict buf, size_t size, size_t count, FILE * __restrict  	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_t count, FILE * __restrict  	 */  	if (__sfvwrite(fp, &uio) != 0)  	    count = (n - uio.uio_resid) / size; -	FUNLOCKFILE(fp); +	FUNLOCKFILE_CANCELSAFE();  	return (count);  } diff --git a/lib/libc/stdio/getc.c b/lib/libc/stdio/getc.c index 4963c8ce68e7..ad2df8a72f5d 100644 --- a/lib/libc/stdio/getc.c +++ b/lib/libc/stdio/getc.c @@ -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);  } diff --git a/lib/libc/stdio/getchar.c b/lib/libc/stdio/getchar.c index 2815072f866e..320f96791ede 100644 --- a/lib/libc/stdio/getchar.c +++ b/lib/libc/stdio/getchar.c @@ -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);  } diff --git a/lib/libc/stdio/getdelim.c b/lib/libc/stdio/getdelim.c index 7e0b2e2b6edb..26c608f8d49c 100644 --- a/lib/libc/stdio/getdelim.c +++ b/lib/libc/stdio/getdelim.c @@ -112,7 +112,7 @@ getdelim(char ** __restrict linep, size_t * __restrict linecapp, int delim,  	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 linecapp, int delim,  		/* 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 linecapp, int delim,  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;  } diff --git a/lib/libc/stdio/gets.c b/lib/libc/stdio/gets.c index c9438515323a..f31221a74c63 100644 --- a/lib/libc/stdio/gets.c +++ b/lib/libc/stdio/gets.c @@ -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);  } diff --git a/lib/libc/stdio/local.h b/lib/libc/stdio/local.h index 7168f6264d73..e4b16872b188 100644 --- a/lib/libc/stdio/local.h +++ b/lib/libc/stdio/local.h @@ -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 */ diff --git a/lib/libc/stdio/perror.c b/lib/libc/stdio/perror.c index 89c079818fb7..15007882b79e 100644 --- a/lib/libc/stdio/perror.c +++ b/lib/libc/stdio/perror.c @@ -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();  } diff --git a/lib/libc/stdio/putc.c b/lib/libc/stdio/putc.c index aaffece49d76..c62d13f5ea4e 100644 --- a/lib/libc/stdio/putc.c +++ b/lib/libc/stdio/putc.c @@ -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);  } diff --git a/lib/libc/stdio/putchar.c b/lib/libc/stdio/putchar.c index 756155902f29..1721a986f854 100644 --- a/lib/libc/stdio/putchar.c +++ b/lib/libc/stdio/putchar.c @@ -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);  } diff --git a/lib/libc/stdio/puts.c b/lib/libc/stdio/puts.c index 124afc73d600..b5fa01a0c41d 100644 --- a/lib/libc/stdio/puts.c +++ b/lib/libc/stdio/puts.c @@ -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);  } diff --git a/lib/libc/stdio/putw.c b/lib/libc/stdio/putw.c index ecd5d095de5e..fc1d81c7c25c 100644 --- a/lib/libc/stdio/putw.c +++ b/lib/libc/stdio/putw.c @@ -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);  } diff --git a/lib/libc/stdio/refill.c b/lib/libc/stdio/refill.c index 71eb2e53dab6..b4b4e015c91f 100644 --- a/lib/libc/stdio/refill.c +++ b/lib/libc/stdio/refill.c @@ -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);  } diff --git a/lib/libc/stdio/scanf.c b/lib/libc/stdio/scanf.c index e377724ac5be..55aa420fa6f5 100644 --- a/lib/libc/stdio/scanf.c +++ b/lib/libc/stdio/scanf.c @@ -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);  } diff --git a/lib/libc/stdio/setvbuf.c b/lib/libc/stdio/setvbuf.c index d39696058616..01db02ea9b64 100644 --- a/lib/libc/stdio/setvbuf.c +++ b/lib/libc/stdio/setvbuf.c @@ -63,7 +63,7 @@ setvbuf(FILE * __restrict fp, char * __restrict buf, int mode, size_t size)  		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);  } diff --git a/lib/libc/stdio/stdio.c b/lib/libc/stdio/stdio.c index 5d6fb9ac5644..c92fb4fb0e83 100644 --- a/lib/libc/stdio/stdio.c +++ b/lib/libc/stdio/stdio.c @@ -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); +} diff --git a/lib/libc/stdio/ungetc.c b/lib/libc/stdio/ungetc.c index 1695af772daa..86e6b81a545b 100644 --- a/lib/libc/stdio/ungetc.c +++ b/lib/libc/stdio/ungetc.c @@ -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);  } diff --git a/lib/libc/stdio/ungetwc.c b/lib/libc/stdio/ungetwc.c index 78bc38d954a0..b47caf4b3248 100644 --- a/lib/libc/stdio/ungetwc.c +++ b/lib/libc/stdio/ungetwc.c @@ -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);  } diff --git a/lib/libc/stdio/vfprintf.c b/lib/libc/stdio/vfprintf.c index bf45bfb421ed..4779ad7a9902 100644 --- a/lib/libc/stdio/vfprintf.c +++ b/lib/libc/stdio/vfprintf.c @@ -274,14 +274,14 @@ vfprintf_l(FILE * __restrict fp, locale_t locale, const char * __restrict fmt0,  	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 diff --git a/lib/libc/stdio/vfscanf.c b/lib/libc/stdio/vfscanf.c index 66dca1ae4720..8416c1b250d6 100644 --- a/lib/libc/stdio/vfscanf.c +++ b/lib/libc/stdio/vfscanf.c @@ -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, va_list ap)  	int ret;  	FIX_LOCALE(locale); -	FLOCKFILE(fp); +	FLOCKFILE_CANCELSAFE(fp);  	ret = __svfscanf(fp, locale, fmt0, ap); -	FUNLOCKFILE(fp); +	FUNLOCKFILE_CANCELSAFE();  	return (ret);  } diff --git a/lib/libc/stdio/vfwprintf.c b/lib/libc/stdio/vfwprintf.c index 9a5381d54b9b..f130c14b1a2c 100644 --- a/lib/libc/stdio/vfwprintf.c +++ b/lib/libc/stdio/vfwprintf.c @@ -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 diff --git a/lib/libc/stdio/vfwscanf.c b/lib/libc/stdio/vfwscanf.c index 63b5dd1be28a..aedc249f8cff 100644 --- a/lib/libc/stdio/vfwscanf.c +++ b/lib/libc/stdio/vfwscanf.c @@ -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 diff --git a/lib/libc/stdio/vscanf.c b/lib/libc/stdio/vscanf.c index 8729c9ca6ba8..309d00c460d2 100644 --- a/lib/libc/stdio/vscanf.c +++ b/lib/libc/stdio/vscanf.c @@ -54,9 +54,9 @@ vscanf_l(locale_t locale, const char * __restrict fmt, __va_list ap)  	int retval;  	FIX_LOCALE(locale); -	FLOCKFILE(stdin); +	FLOCKFILE_CANCELSAFE(stdin);  	retval = __svfscanf(stdin, locale, fmt, ap); -	FUNLOCKFILE(stdin); +	FUNLOCKFILE_CANCELSAFE();  	return (retval);  }  int | 
