Index: head/lib/libc/stdio/fclose.c
===================================================================
--- head/lib/libc/stdio/fclose.c	(revision 320471)
+++ head/lib/libc/stdio/fclose.c	(revision 320472)
@@ -1,138 +1,138 @@
 /*-
  * Copyright (c) 1990, 1993 The Regents of the University of California.
  * Copyright (c) 2013 Mariusz Zaborski <oshogbo@FreeBSD.org>
  * All rights reserved.
  *
  * This code is derived from software contributed to Berkeley by
  * Chris Torek.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
 static char sccsid[] = "@(#)fclose.c	8.1 (Berkeley) 6/4/93";
 #endif /* LIBC_SCCS and not lint */
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
 #include "namespace.h"
 #include <errno.h>
 #include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include "un-namespace.h"
 #include <spinlock.h>
 #include "libc_private.h"
 #include "local.h"
 
 static int
 cleanfile(FILE *fp, bool c)
 {
 	int r;
 
 	r = fp->_flags & __SWR ? __sflush(fp) : 0;
 	if (c) {
 		if (fp->_close != NULL && (*fp->_close)(fp->_cookie) < 0)
 			r = EOF;
 	}
 
 	if (fp->_flags & __SMBF)
 		free((char *)fp->_bf._base);
 	if (HASUB(fp))
 		FREEUB(fp);
 	if (HASLB(fp))
 		FREELB(fp);
 	fp->_file = -1;
 	fp->_r = fp->_w = 0;	/* Mess up if reaccessed. */
 
 	/*
 	 * Lock the spinlock used to protect __sglue list walk in
 	 * __sfp().  The __sfp() uses fp->_flags == 0 test as an
 	 * indication of the unused FILE.
 	 *
 	 * Taking the lock prevents possible compiler or processor
 	 * reordering of the writes performed before the final _flags
 	 * cleanup, making sure that we are done with the FILE before
 	 * it is considered available.
 	 */
 	STDIO_THREAD_LOCK();
 	fp->_flags = 0;		/* Release this FILE for reuse. */
 	STDIO_THREAD_UNLOCK();
 
 	return (r);
 }
 
 int
 fdclose(FILE *fp, int *fdp)
 {
 	int r, err;
 
 	if (fdp != NULL)
 		*fdp = -1;
 
 	if (fp->_flags == 0) {	/* not open! */
 		errno = EBADF;
 		return (EOF);
 	}
 
-	FLOCKFILE(fp);
+	FLOCKFILE_CANCELSAFE(fp);
 	r = 0;
 	if (fp->_close != __sclose) {
 		r = EOF;
 		errno = EOPNOTSUPP;
 	} else if (fp->_file < 0) {
 		r = EOF;
 		errno = EBADF;
 	}
 	if (r == EOF) {
 		err = errno;
 		(void)cleanfile(fp, true);
 		errno = err;
 	} else {
 		if (fdp != NULL)
 			*fdp = fp->_file;
 		r = cleanfile(fp, false);
 	}
-	FUNLOCKFILE(fp);
+	FUNLOCKFILE_CANCELSAFE();
 
 	return (r);
 }
 
 int
 fclose(FILE *fp)
 {
 	int r;
 
 	if (fp->_flags == 0) {	/* not open! */
 		errno = EBADF;
 		return (EOF);
 	}
 
-	FLOCKFILE(fp);
+	FLOCKFILE_CANCELSAFE(fp);
 	r = cleanfile(fp, true);
-	FUNLOCKFILE(fp);
+	FUNLOCKFILE_CANCELSAFE();
 
 	return (r);
 }
Index: head/lib/libc/stdio/fflush.c
===================================================================
--- head/lib/libc/stdio/fflush.c	(revision 320471)
+++ head/lib/libc/stdio/fflush.c	(revision 320472)
@@ -1,150 +1,150 @@
 /*-
  * Copyright (c) 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
  *
  * This code is derived from software contributed to Berkeley by
  * Chris Torek.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
 static char sccsid[] = "@(#)fflush.c	8.1 (Berkeley) 6/4/93";
 #endif /* LIBC_SCCS and not lint */
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
 #include "namespace.h"
 #include <errno.h>
 #include <stdio.h>
 #include "un-namespace.h"
 #include "libc_private.h"
 #include "local.h"
 
 static int	sflush_locked(FILE *);
 
 /*
  * Flush a single file, or (if fp is NULL) all files.
  * MT-safe version
  */
 int
 fflush(FILE *fp)
 {
 	int retval;
 
 	if (fp == NULL)
 		return (_fwalk(sflush_locked));
-	FLOCKFILE(fp);
+	FLOCKFILE_CANCELSAFE(fp);
 
 	/*
 	 * There is disagreement about the correct behaviour of fflush()
 	 * when passed a file which is not open for writing.  According to
 	 * the ISO C standard, the behaviour is undefined.
 	 * Under linux, such an fflush returns success and has no effect;
 	 * under Windows, such an fflush is documented as behaving instead
 	 * as fpurge().
 	 * Given that applications may be written with the expectation of
 	 * either of these two behaviours, the only safe (non-astonishing)
 	 * option is to return EBADF and ask that applications be fixed.
 	 * SUSv3 now requires that fflush() returns success on a read-only
 	 * stream.
 	 *
 	 */
 	if ((fp->_flags & (__SWR | __SRW)) == 0)
 		retval = 0;
 	else
 		retval = __sflush(fp);
-	FUNLOCKFILE(fp);
+	FUNLOCKFILE_CANCELSAFE();
 	return (retval);
 }
 
 /*
  * Flush a single file, or (if fp is NULL) all files.
  * Non-MT-safe version
  */
 int
 __fflush(FILE *fp)
 {
 	int retval;
 
 	if (fp == NULL)
 		return (_fwalk(sflush_locked));
 	if ((fp->_flags & (__SWR | __SRW)) == 0)
 		retval = 0;
 	else
 		retval = __sflush(fp);
 	return (retval);
 }
 
 int
 __sflush(FILE *fp)
 {
 	unsigned char *p;
 	int n, t;
 
 	t = fp->_flags;
 	if ((t & __SWR) == 0)
 		return (0);
 
 	if ((p = fp->_bf._base) == NULL)
 		return (0);
 
 	n = fp->_p - p;		/* write this much */
 
 	/*
 	 * Set these immediately to avoid problems with longjmp and to allow
 	 * exchange buffering (via setvbuf) in user write function.
 	 */
 	fp->_p = p;
 	fp->_w = t & (__SLBF|__SNBF) ? 0 : fp->_bf._size;
 
 	for (; n > 0; n -= t, p += t) {
 		t = _swrite(fp, (char *)p, n);
 		if (t <= 0) {
 			/* Reset _p and _w. */
 			if (p > fp->_p) {
 				/* Some was written. */
 				memmove(fp->_p, p, n);
 				fp->_p += n;
 				if ((fp->_flags & (__SLBF | __SNBF)) == 0)
 					fp->_w -= n;
 			}
 			fp->_flags |= __SERR;
 			return (EOF);
 		}
 	}
 	return (0);
 }
 
 static int
 sflush_locked(FILE *fp)
 {
 	int	ret;
 
-	FLOCKFILE(fp);
+	FLOCKFILE_CANCELSAFE(fp);
 	ret = __sflush(fp);
-	FUNLOCKFILE(fp);
+	FUNLOCKFILE_CANCELSAFE();
 	return (ret);
 }
Index: head/lib/libc/stdio/fgetc.c
===================================================================
--- head/lib/libc/stdio/fgetc.c	(revision 320471)
+++ head/lib/libc/stdio/fgetc.c	(revision 320472)
@@ -1,55 +1,55 @@
 /*-
  * Copyright (c) 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
  *
  * This code is derived from software contributed to Berkeley by
  * Chris Torek.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
 static char sccsid[] = "@(#)fgetc.c	8.1 (Berkeley) 6/4/93";
 #endif /* LIBC_SCCS and not lint */
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
 #include "namespace.h"
 #include <stdio.h>
 #include "un-namespace.h"
 #include "libc_private.h"
 #include "local.h"
 
 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);
 }
Index: head/lib/libc/stdio/fgetln.c
===================================================================
--- head/lib/libc/stdio/fgetln.c	(revision 320471)
+++ head/lib/libc/stdio/fgetln.c	(revision 320472)
@@ -1,174 +1,174 @@
 /*-
  * Copyright (c) 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
  *
  * This code is derived from software contributed to Berkeley by
  * Chris Torek.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
 static char sccsid[] = "@(#)fgetln.c	8.2 (Berkeley) 1/2/94";
 #endif /* LIBC_SCCS and not lint */
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
 #include "namespace.h"
 #include <errno.h>
 #include <limits.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include "un-namespace.h"
 #include "libc_private.h"
 #include "local.h"
 
 /*
  * Expand the line buffer.  Return -1 on error.
 #ifdef notdef
  * The `new size' does not account for a terminating '\0',
  * so we add 1 here.
 #endif
  */
 int
 __slbexpand(FILE *fp, size_t newsize)
 {
 	void *p;
 
 #ifdef notdef
 	++newsize;
 #endif
 	if (fp->_lb._size >= newsize)
 		return (0);
 	if (newsize > INT_MAX) {
 		errno = ENOMEM;
 		return (-1);
 	}
 	if ((p = realloc(fp->_lb._base, newsize)) == NULL)
 		return (-1);
 	fp->_lb._base = p;
 	fp->_lb._size = newsize;
 	return (0);
 }
 
 /*
  * Get an input line.  The returned pointer often (but not always)
  * points into a stdio buffer.  Fgetln does not alter the text of
  * the returned line (which is thus not a C string because it will
  * not necessarily end with '\0'), but does allow callers to modify
  * it if they wish.  Thus, we set __SMOD in case the caller does.
  */
 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
 		 * the text.
 		 */
 		p++;		/* advance over it */
 		ret = (char *)fp->_p;
 		*lenp = len = p - fp->_p;
 		fp->_flags |= __SMOD;
 		fp->_r -= len;
 		fp->_p = p;
-		FUNLOCKFILE(fp);
-		return (ret);
+		goto end;
 	}
 
 	/*
 	 * We have to copy the current buffered data to the line buffer.
 	 * As a bonus, though, we can leave off the __SMOD.
 	 *
 	 * OPTIMISTIC is length that we (optimistically) expect will
 	 * accommodate the `rest' of the string, on each trip through the
 	 * loop below.
 	 */
 #define OPTIMISTIC 80
 
 	for (len = fp->_r, off = 0;; len += fp->_r) {
 		size_t diff;
 
 		/*
 		 * Make sure there is room for more bytes.  Copy data from
 		 * file buffer to line buffer, refill file and look for
 		 * newline.  The loop stops only when we find a newline.
 		 */
 		if (__slbexpand(fp, len + OPTIMISTIC))
 			goto error;
 		(void)memcpy((void *)(fp->_lb._base + off), (void *)fp->_p,
 		    len - off);
 		off = len;
 		if (__srefill(fp)) {
 			if (__sfeof(fp))
 				break;
 			goto error;
 		}
 		if ((p = memchr((void *)fp->_p, '\n', (size_t)fp->_r)) == NULL)
 			continue;
 
 		/* got it: finish up the line (like code above) */
 		p++;
 		diff = p - fp->_p;
 		len += diff;
 		if (__slbexpand(fp, len))
 			goto error;
 		(void)memcpy((void *)(fp->_lb._base + off), (void *)fp->_p,
 		    diff);
 		fp->_r -= diff;
 		fp->_p = p;
 		break;
 	}
 	*lenp = len;
 #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;
 }
Index: head/lib/libc/stdio/fgets.c
===================================================================
--- head/lib/libc/stdio/fgets.c	(revision 320471)
+++ head/lib/libc/stdio/fgets.c	(revision 320472)
@@ -1,115 +1,117 @@
 /*-
  * Copyright (c) 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
  *
  * This code is derived from software contributed to Berkeley by
  * Chris Torek.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
 static char sccsid[] = "@(#)fgets.c	8.2 (Berkeley) 12/22/93";
 #endif /* LIBC_SCCS and not lint */
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
 #include "namespace.h"
 #include <errno.h>
 #include <stdio.h>
 #include <string.h>
 #include "un-namespace.h"
 #include "local.h"
 #include "libc_private.h"
 
 /*
  * Read at most n-1 characters from the given file.
  * Stop when a newline has been read, or the count runs out.
  * Return first argument, or NULL if no characters were read.
  */
 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;
 	n--;			/* leave space for NUL */
 	while (n != 0) {
 		/*
 		 * If the buffer is empty, refill it.
 		 */
 		if ((len = fp->_r) <= 0) {
 			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;
 			}
 			len = fp->_r;
 		}
 		p = fp->_p;
 
 		/*
 		 * Scan through at most n bytes of the current buffer,
 		 * looking for '\n'.  If found, copy up to and including
 		 * newline, and stop.  Otherwise, copy entire chunk
 		 * and loop.
 		 */
 		if (len > n)
 			len = n;
 		t = memchr((void *)p, '\n', len);
 		if (t != NULL) {
 			len = ++t - p;
 			fp->_r -= len;
 			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;
 		(void)memcpy((void *)s, (void *)p, len);
 		s += len;
 		n -= len;
 	}
 	*s = 0;
-	FUNLOCKFILE(fp);
-	return (buf);
+	ret = buf;
+end:
+	FUNLOCKFILE_CANCELSAFE();
+	return (ret);
 }
Index: head/lib/libc/stdio/fgetwc.c
===================================================================
--- head/lib/libc/stdio/fgetwc.c	(revision 320471)
+++ head/lib/libc/stdio/fgetwc.c	(revision 320472)
@@ -1,109 +1,109 @@
 /*-
  * Copyright (c) 2002-2004 Tim J. Robbins.
  * All rights reserved.
  *
  * Copyright (c) 2011 The FreeBSD Foundation
  * All rights reserved.
  * Portions of this software were developed by David Chisnall
  * under sponsorship from the FreeBSD Foundation.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
 
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
 #include "namespace.h"
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <wchar.h>
 #include "un-namespace.h"
 #include "libc_private.h"
 #include "local.h"
 #include "mblocal.h"
 #include "xlocale_private.h"
 
 /*
  * MT-safe version.
  */
 wint_t
 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);
 }
 
 wint_t
 fgetwc(FILE *fp)
 {
 	return fgetwc_l(fp, __get_locale());
 }
 
 /*
  * Internal (non-MPSAFE) version of fgetwc().  This version takes an
  * mbstate_t argument specifying the initial conversion state.  For
  * wide streams, this should always be fp->_mbstate.  On return, *nread
  * is set to the number of bytes read.
  */
 wint_t 
 __fgetwc_mbs(FILE *fp, mbstate_t *mbs, int *nread, locale_t locale)
 {
 	wchar_t wc;
 	size_t nconv;
 	struct xlocale_ctype *l = XLOCALE_CTYPE(locale);
 
 	*nread = 0;
 	if (fp->_r <= 0 && __srefill(fp))
 		return (WEOF);
 	do {
 		nconv = l->__mbrtowc(&wc, fp->_p, fp->_r, mbs);
 		if (nconv == (size_t)-1) {
 			fp->_flags |= __SERR;
 			return (WEOF);
 		} else if (nconv == (size_t)-2)
 			continue;
 		else if (nconv == 0) {
 			fp->_p++;
 			fp->_r--;
 			(*nread)++;
 			return (L'\0');
 		} else {
 			fp->_p += nconv;
 			fp->_r -= nconv;
 			*nread += nconv;
 			return (wc);
 		}
 	} while (__srefill(fp) == 0);
 	if (__sfeof(fp)) {
 		fp->_flags |= __SERR;
 		errno = EILSEQ;
 	}
 	return (WEOF);
 }
Index: head/lib/libc/stdio/fgetwln.c
===================================================================
--- head/lib/libc/stdio/fgetwln.c	(revision 320471)
+++ head/lib/libc/stdio/fgetwln.c	(revision 320472)
@@ -1,94 +1,97 @@
 /*-
  * Copyright (c) 2002-2004 Tim J. Robbins.
  * All rights reserved.
  *
  * Copyright (c) 2011 The FreeBSD Foundation
  * All rights reserved.
  * Portions of this software were developed by David Chisnall
  * under sponsorship from the FreeBSD Foundation.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
 
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
 #include "namespace.h"
 #include <stdio.h>
 #include <wchar.h>
 #include "un-namespace.h"
 #include "libc_private.h"
 #include "local.h"
 #include "xlocale_private.h"
 
 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;
 	fp->_flags &= ~__SERR;
 
 	len = 0;
 	while ((wc = __fgetwc(fp, locale)) != WEOF) {
 #define	GROW	512
 		if (len * sizeof(wchar_t) >= fp->_lb._size &&
 		    __slbexpand(fp, (len + GROW) * sizeof(wchar_t))) {
 			fp->_flags |= __SERR;
 			goto error;
 		}
 		*((wchar_t *)fp->_lb._base + len++) = wc;
 		if (wc == L'\n')
 			break;
 	}
 	/* fgetwc(3) may set both __SEOF and __SERR at once. */
 	if (__sferror(fp))
 		goto error;
 
 	fp->_flags |= savserr;
 	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 *
 fgetwln(FILE * __restrict fp, size_t *lenp)
 {
 	return fgetwln_l(fp, lenp, __get_locale());
 }
Index: head/lib/libc/stdio/fgetws.c
===================================================================
--- head/lib/libc/stdio/fgetws.c	(revision 320471)
+++ head/lib/libc/stdio/fgetws.c	(revision 320472)
@@ -1,128 +1,130 @@
 /*-
  * Copyright (c) 2002-2004 Tim J. Robbins.
  * All rights reserved.
  *
  * Copyright (c) 2011 The FreeBSD Foundation
  * All rights reserved.
  * Portions of this software were developed by David Chisnall
  * under sponsorship from the FreeBSD Foundation.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
 
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
 #include "namespace.h"
 #include <errno.h>
 #include <stdio.h>
 #include <string.h>
 #include <wchar.h>
 #include "un-namespace.h"
 #include "libc_private.h"
 #include "local.h"
 #include "mblocal.h"
 
 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) {
 		fp->_flags |= __SERR;
 		errno = EINVAL;
 		goto error;
 	}
 
 	wsp = ws;
 	if (n == 1)
 		goto ok;
 
 	if (fp->_r <= 0 && __srefill(fp))
 		/* EOF or ferror */
 		goto error;
 
 	sret = 0;
 	do {
 		src = fp->_p;
 		nl = memchr(fp->_p, '\n', fp->_r);
 		nconv = l->__mbsnrtowcs(wsp, &src,
 		    nl != NULL ? (nl - fp->_p + 1) : fp->_r,
 		    n - 1, &fp->_mbstate);
 		if (nconv == (size_t)-1) {
 			/* Conversion error */
 			fp->_flags |= __SERR;
 			goto error;
 		}
 		if (src == NULL) {
 			/*
 			 * We hit a null byte. Increment the character count,
 			 * since mbsnrtowcs()'s return value doesn't include
 			 * the terminating null, then resume conversion
 			 * after the null.
 			 */
 			nconv++;
 			src = memchr(fp->_p, '\0', fp->_r);
 			src++;
 		}
 		fp->_r -= (unsigned char *)src - fp->_p;
 		fp->_p = (unsigned char *)src;
 		n -= nconv;
 		wsp += nconv;
 	} while ((wsp == ws || wsp[-1] != L'\n') && n > 1 && (fp->_r > 0 ||
 	    (sret = __srefill(fp)) == 0));
 	if (sret && !__sfeof(fp))
 		/* ferror */
 		goto error;
 	if (!l->__mbsinit(&fp->_mbstate)) {
 		/* Incomplete character */
 		fp->_flags |= __SERR;
 		errno = EILSEQ;
 		goto error;
 	}
 	if (wsp == ws)
 		/* EOF */
 		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 *
 fgetws(wchar_t * __restrict ws, int n, FILE * __restrict fp)
 {
 	return fgetws_l(ws, n, fp, __get_locale());
 }
Index: head/lib/libc/stdio/fputc.c
===================================================================
--- head/lib/libc/stdio/fputc.c	(revision 320471)
+++ head/lib/libc/stdio/fputc.c	(revision 320472)
@@ -1,55 +1,55 @@
 /*-
  * Copyright (c) 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
  *
  * This code is derived from software contributed to Berkeley by
  * Chris Torek.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
 static char sccsid[] = "@(#)fputc.c	8.1 (Berkeley) 6/4/93";
 #endif /* LIBC_SCCS and not lint */
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
 #include "namespace.h"
 #include <stdio.h>
 #include "un-namespace.h"
 #include "local.h"
 #include "libc_private.h"
 
 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);
 }
Index: head/lib/libc/stdio/fputs.c
===================================================================
--- head/lib/libc/stdio/fputs.c	(revision 320471)
+++ head/lib/libc/stdio/fputs.c	(revision 320472)
@@ -1,69 +1,69 @@
 /*-
  * Copyright (c) 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
  *
  * This code is derived from software contributed to Berkeley by
  * Chris Torek.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
 static char sccsid[] = "@(#)fputs.c	8.1 (Berkeley) 6/4/93";
 #endif /* LIBC_SCCS and not lint */
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
 #include "namespace.h"
 #include <limits.h>
 #include <stdio.h>
 #include <string.h>
 #include "un-namespace.h"
 #include "fvwrite.h"
 #include "libc_private.h"
 #include "local.h"
 
 /*
  * Write the given string to the given file.
  */
 int
 fputs(const char * __restrict s, FILE * __restrict fp)
 {
 	int retval;
 	struct __suio uio;
 	struct __siov iov;
 
 	iov.iov_base = (void *)s;
 	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);
 }
Index: head/lib/libc/stdio/fputwc.c
===================================================================
--- head/lib/libc/stdio/fputwc.c	(revision 320471)
+++ head/lib/libc/stdio/fputwc.c	(revision 320472)
@@ -1,88 +1,88 @@
 /*-
  * Copyright (c) 2002-2004 Tim J. Robbins.
  * All rights reserved.
  *
  * Copyright (c) 2011 The FreeBSD Foundation
  * All rights reserved.
  * Portions of this software were developed by David Chisnall
  * under sponsorship from the FreeBSD Foundation.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
 
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
 #include "namespace.h"
 #include <errno.h>
 #include <limits.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <wchar.h>
 #include "un-namespace.h"
 #include "libc_private.h"
 #include "local.h"
 #include "mblocal.h"
 
 /*
  * Non-MT-safe version.
  */
 wint_t
 __fputwc(wchar_t wc, FILE *fp, locale_t locale)
 {
 	char buf[MB_LEN_MAX];
 	size_t i, len;
 	struct xlocale_ctype *l = XLOCALE_CTYPE(locale);
 
 	if ((len = l->__wcrtomb(buf, wc, &fp->_mbstate)) == (size_t)-1) {
 		fp->_flags |= __SERR;
 		return (WEOF);
 	}
 
 	for (i = 0; i < len; i++)
 		if (__sputc((unsigned char)buf[i], fp) == EOF)
 			return (WEOF);
 
 	return ((wint_t)wc);
 }
 
 /*
  * MT-safe version.
  */
 wint_t
 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);
 }
 wint_t
 fputwc(wchar_t wc, FILE *fp)
 {
 	return fputwc_l(wc, fp, __get_locale());
 }
Index: head/lib/libc/stdio/fputws.c
===================================================================
--- head/lib/libc/stdio/fputws.c	(revision 320471)
+++ head/lib/libc/stdio/fputws.c	(revision 320472)
@@ -1,86 +1,86 @@
 /*-
  * Copyright (c) 2002-2004 Tim J. Robbins.
  * All rights reserved.
  *
  * Copyright (c) 2011 The FreeBSD Foundation
  * All rights reserved.
  * Portions of this software were developed by David Chisnall
  * under sponsorship from the FreeBSD Foundation.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
 
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
 #include "namespace.h"
 #include <errno.h>
 #include <limits.h>
 #include <stdio.h>
 #include <wchar.h>
 #include "un-namespace.h"
 #include "fvwrite.h"
 #include "libc_private.h"
 #include "local.h"
 #include "mblocal.h"
 
 int
 fputws_l(const wchar_t * __restrict ws, FILE * __restrict fp, locale_t locale)
 {
 	size_t nbytes;
 	char buf[BUFSIZ];
 	struct __suio uio;
 	struct __siov iov;
 	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;
 	wsp = ws;
 	do {
 		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
 fputws(const wchar_t * __restrict ws, FILE * __restrict fp)
 {
 	return fputws_l(ws, fp, __get_locale());
 }
Index: head/lib/libc/stdio/fread.c
===================================================================
--- head/lib/libc/stdio/fread.c	(revision 320471)
+++ head/lib/libc/stdio/fread.c	(revision 320472)
@@ -1,115 +1,115 @@
 /*-
  * Copyright (c) 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
  *
  * This code is derived from software contributed to Berkeley by
  * Chris Torek.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
 static char sccsid[] = "@(#)fread.c	8.2 (Berkeley) 12/11/93";
 #endif /* LIBC_SCCS and not lint */
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
 #include "namespace.h"
 #include <errno.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <string.h>
 #include "un-namespace.h"
 #include "local.h"
 #include "libc_private.h"
 
 /*
  * MT-safe version
  */
 
 size_t
 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);
 }
 
 size_t
 __fread(void * __restrict buf, size_t size, size_t count, FILE * __restrict fp)
 {
 	size_t resid;
 	char *p;
 	int r;
 	size_t total;
 
 	/*
 	 * ANSI and SUSv2 require a return value of 0 if size or count are 0.
 	 */
 	if ((count == 0) || (size == 0))
 		return (0);
 
 	/*
 	 * Check for integer overflow.  As an optimization, first check that
 	 * at least one of {count, size} is at least 2^16, since if both
 	 * values are less than that, their product can't possible overflow
 	 * (size_t is always at least 32 bits on FreeBSD).
 	 */
 	if (((count | size) > 0xFFFF) &&
 	    (count > SIZE_MAX / size)) {
 		errno = EINVAL;
 		fp->_flags |= __SERR;
 		return (0);
 	}
 
 	/*
 	 * Compute the (now required to not overflow) number of bytes to
 	 * read and actually do the work.
 	 */
 	resid = count * size;
 	ORIENT(fp, -1);
 	if (fp->_r < 0)
 		fp->_r = 0;
 	total = resid;
 	p = buf;
 	while (resid > (r = fp->_r)) {
 		(void)memcpy((void *)p, (void *)fp->_p, (size_t)r);
 		fp->_p += r;
 		/* fp->_r = 0 ... done in __srefill */
 		p += r;
 		resid -= r;
 		if (__srefill(fp)) {
 			/* no more input: return partial result */
 			return ((total - resid) / size);
 		}
 	}
 	(void)memcpy((void *)p, (void *)fp->_p, resid);
 	fp->_r -= resid;
 	fp->_p += resid;
 	return (count);
 }
Index: head/lib/libc/stdio/freopen.c
===================================================================
--- head/lib/libc/stdio/freopen.c	(revision 320471)
+++ head/lib/libc/stdio/freopen.c	(revision 320472)
@@ -1,250 +1,251 @@
 /*-
  * Copyright (c) 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
  *
  * This code is derived from software contributed to Berkeley by
  * Chris Torek.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
 static char sccsid[] = "@(#)freopen.c	8.1 (Berkeley) 6/4/93";
 #endif /* LIBC_SCCS and not lint */
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
 #include "namespace.h"
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <errno.h>
 #include <limits.h>
 #include <unistd.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include "un-namespace.h"
 #include "libc_private.h"
 #include "local.h"
 
 /*
  * Re-direct an existing, open (probably) file to some other file.
  * ANSI is written such that the original file gets closed if at
  * all possible, no matter what.
  */
 FILE *
 freopen(const char * __restrict file, const char * __restrict mode,
     FILE * __restrict fp)
 {
 	int f;
 	int dflags, flags, isopen, oflags, sverrno, wantfd;
 
 	if ((flags = __sflags(mode, &oflags)) == 0) {
 		sverrno = errno;
 		(void) fclose(fp);
 		errno = sverrno;
 		return (NULL);
 	}
 
-	FLOCKFILE(fp);
+	FLOCKFILE_CANCELSAFE(fp);
 
 	if (!__sdidinit)
 		__sinit();
 
 	/*
 	 * If the filename is a NULL pointer, the caller is asking us to
 	 * re-open the same file with a different mode. We allow this only
 	 * if the modes are compatible.
 	 */
 	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);
 		if ((oflags ^ dflags) & O_APPEND) {
 			dflags &= ~O_APPEND;
 			dflags |= oflags & O_APPEND;
 			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)
 			(void) ftruncate(fp->_file, (off_t)0);
 		if (!(oflags & O_APPEND))
 			(void) _sseek(fp, (fpos_t)0, SEEK_SET);
 		if (oflags & O_CLOEXEC)
 			(void) _fcntl(fp->_file, F_SETFD, FD_CLOEXEC);
 		f = fp->_file;
 		isopen = 0;
 		wantfd = -1;
 		goto finish;
 	}
 
 	/*
 	 * There are actually programs that depend on being able to "freopen"
 	 * descriptors that weren't originally open.  Keep this from breaking.
 	 * Remember whether the stream was open to begin with, and which file
 	 * descriptor (if any) was associated with it.  If it was attached to
 	 * a descriptor, defer closing it; freopen("/dev/stdin", "r", stdin)
 	 * should work.  This is unnecessary if it was not a Unix file.
 	 */
 	if (fp->_flags == 0) {
 		fp->_flags = __SEOF;	/* hold on to it */
 		isopen = 0;
 		wantfd = -1;
 	} else {
 		/* flush the stream; ANSI doesn't require this. */
 		if (fp->_flags & __SWR)
 			(void) __sflush(fp);
 		/* if close is NULL, closing is a no-op, hence pointless */
 		isopen = fp->_close != NULL;
 		if ((wantfd = fp->_file) < 0 && isopen) {
 			(void) (*fp->_close)(fp->_cookie);
 			isopen = 0;
 		}
 	}
 
 	/* Get a new descriptor to refer to the new file. */
 	f = _open(file, oflags, DEFFILEMODE);
 	/* If out of fd's close the old one and try again. */
 	if (f < 0 && isopen && wantfd > STDERR_FILENO &&
 	    (errno == ENFILE || errno == EMFILE)) {
 		(void) (*fp->_close)(fp->_cookie);
 		isopen = 0;
 		wantfd = -1;
 		f = _open(file, oflags, DEFFILEMODE);
 	}
 	sverrno = errno;
 
 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 (fp->_flags & __SMBF)
 		free((char *)fp->_bf._base);
 	fp->_w = 0;
 	fp->_r = 0;
 	fp->_p = NULL;
 	fp->_bf._base = NULL;
 	fp->_bf._size = 0;
 	fp->_lbfsize = 0;
 	if (HASUB(fp))
 		FREEUB(fp);
 	fp->_ub._size = 0;
 	if (HASLB(fp))
 		FREELB(fp);
 	fp->_lb._size = 0;
 	fp->_orientation = 0;
 	memset(&fp->_mbstate, 0, sizeof(mbstate_t));
 	fp->_flags2 = 0;
 
 	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 */
-		return (NULL);
+		fp = NULL;
+		goto end;
 	}
 
 	/*
 	 * If reopening something that was open before on a real file, try
 	 * to maintain the descriptor.  Various C library routines (perror)
 	 * assume stderr is always fd STDERR_FILENO, even if being freopen'd.
 	 */
 	if (wantfd >= 0) {
 		if ((oflags & O_CLOEXEC ? _fcntl(f, F_DUP2FD_CLOEXEC, wantfd) :
 		    _dup2(f, wantfd)) >= 0) {
 			(void)_close(f);
 			f = wantfd;
 		} else
 			(void)_close(fp->_file);
 	}
 
 	/*
 	 * File descriptors are a full int, but _file is only a short.
 	 * If we get a valid file descriptor that is greater than
 	 * SHRT_MAX, then the fd will get sign-extended into an
 	 * invalid file descriptor.  Handle this case by failing the
 	 * open.
 	 */
 	if (f > SHRT_MAX) {
 		fp->_flags = 0;		/* set it free */
-		FUNLOCKFILE(fp);
 		errno = EMFILE;
-		return (NULL);
+		fp = NULL;
+		goto end;
 	}
 
 	fp->_flags = flags;
 	fp->_file = f;
 	fp->_cookie = fp;
 	fp->_read = __sread;
 	fp->_write = __swrite;
 	fp->_seek = __sseek;
 	fp->_close = __sclose;
 	/*
 	 * When opening in append mode, even though we use O_APPEND,
 	 * we need to seek to the end so that ftell() gets the right
 	 * answer.  If the user then alters the seek pointer, or
 	 * the file extends, this will fail, but there is not much
 	 * we can do about this.  (We could set __SAPP and check in
 	 * fseek and ftell.)
 	 */
 	if (oflags & O_APPEND) {
 		fp->_flags2 |= __S2OAP;
 		(void) _sseek(fp, (fpos_t)0, SEEK_END);
 	}
-	FUNLOCKFILE(fp);
+end:
+	FUNLOCKFILE_CANCELSAFE();
 	return (fp);
 }
Index: head/lib/libc/stdio/fscanf.c
===================================================================
--- head/lib/libc/stdio/fscanf.c	(revision 320471)
+++ head/lib/libc/stdio/fscanf.c	(revision 320472)
@@ -1,78 +1,78 @@
 /*-
  * Copyright (c) 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
  *
  * This code is derived from software contributed to Berkeley by
  * Chris Torek.
  *
  * Copyright (c) 2011 The FreeBSD Foundation
  * All rights reserved.
  * Portions of this software were developed by David Chisnall
  * under sponsorship from the FreeBSD Foundation.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
 static char sccsid[] = "@(#)fscanf.c	8.1 (Berkeley) 6/4/93";
 #endif /* LIBC_SCCS and not lint */
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
 #include "namespace.h"
 #include <stdio.h>
 #include <stdarg.h>
 #include "un-namespace.h"
 #include "libc_private.h"
 #include "local.h"
 #include "xlocale_private.h"
 
 int
 fscanf(FILE * __restrict fp, char const * __restrict fmt, ...)
 {
 	int ret;
 	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
 fscanf_l(FILE * __restrict fp, locale_t locale, char const * __restrict fmt, ...)
 {
 	int ret;
 	va_list ap;
 	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);
 }
Index: head/lib/libc/stdio/fseek.c
===================================================================
--- head/lib/libc/stdio/fseek.c	(revision 320471)
+++ head/lib/libc/stdio/fseek.c	(revision 320472)
@@ -1,301 +1,301 @@
 /*-
  * Copyright (c) 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
  *
  * This code is derived from software contributed to Berkeley by
  * Chris Torek.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
 static char sccsid[] = "@(#)fseek.c	8.3 (Berkeley) 1/2/94";
 #endif /* LIBC_SCCS and not lint */
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
 #include "namespace.h"
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <limits.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include "un-namespace.h"
 #include "local.h"
 #include "libc_private.h"
 
 #define	POS_ERR	(-(fpos_t)1)
 
 int
 fseek(FILE *fp, long offset, int whence)
 {
 	int ret;
 	int serrno = errno;
 
 	/* make sure stdio is set up */
 	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);
 }
 
 int
 fseeko(FILE *fp, off_t offset, int whence)
 {
 	int ret;
 	int serrno = errno;
 
 	/* make sure stdio is set up */
 	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);
 }
 
 /*
  * Seek the given file to the given offset.
  * `Whence' must be one of the three SEEK_* macros.
  */
 int
 _fseeko(FILE *fp, off_t offset, int whence, int ltest)
 {
 	fpos_t (*seekfn)(void *, fpos_t, int);
 	fpos_t target, curoff, ret;
 	size_t n;
 	struct stat st;
 	int havepos;
 
 	/*
 	 * Have to be able to seek.
 	 */
 	if ((seekfn = fp->_seek) == NULL) {
 		errno = ESPIPE;		/* historic practice */
 		return (-1);
 	}
 
 	/*
 	 * Change any SEEK_CUR to SEEK_SET, and check `whence' argument.
 	 * After this, whence is either SEEK_SET or SEEK_END.
 	 */
 	switch (whence) {
 
 	case SEEK_CUR:
 		/*
 		 * In order to seek relative to the current stream offset,
 		 * we have to first find the current stream offset via
 		 * ftell (see ftell for details).
 		 */
 		if (_ftello(fp, &curoff))
 			return (-1);
 		if (curoff < 0) {
 			/* Unspecified position because of ungetc() at 0 */
 			errno = ESPIPE;
 			return (-1);
 		}
 		if (offset > 0 && curoff > OFF_MAX - offset) {
 			errno = EOVERFLOW;
 			return (-1);
 		}
 		offset += curoff;
 		if (offset < 0) {
 			errno = EINVAL;
 			return (-1);
 		}
 		if (ltest && offset > LONG_MAX) {
 			errno = EOVERFLOW;
 			return (-1);
 		}
 		whence = SEEK_SET;
 		havepos = 1;
 		break;
 
 	case SEEK_SET:
 		if (offset < 0) {
 			errno = EINVAL;
 			return (-1);
 		}
 	case SEEK_END:
 		curoff = 0;		/* XXX just to keep gcc quiet */
 		havepos = 0;
 		break;
 
 	default:
 		errno = EINVAL;
 		return (-1);
 	}
 
 	/*
 	 * Can only optimise if:
 	 *	reading (and not reading-and-writing);
 	 *	not unbuffered; and
 	 *	this is a `regular' Unix file (and hence seekfn==__sseek).
 	 * We must check __NBF first, because it is possible to have __NBF
 	 * and __SOPT both set.
 	 */
 	if (fp->_bf._base == NULL)
 		__smakebuf(fp);
 	if (fp->_flags & (__SWR | __SRW | __SNBF | __SNPT))
 		goto dumb;
 	if ((fp->_flags & __SOPT) == 0) {
 		if (seekfn != __sseek ||
 		    fp->_file < 0 || _fstat(fp->_file, &st) ||
 		    (st.st_mode & S_IFMT) != S_IFREG) {
 			fp->_flags |= __SNPT;
 			goto dumb;
 		}
 		fp->_blksize = st.st_blksize;
 		fp->_flags |= __SOPT;
 	}
 
 	/*
 	 * We are reading; we can try to optimise.
 	 * Figure out where we are going and where we are now.
 	 */
 	if (whence == SEEK_SET)
 		target = offset;
 	else {
 		if (_fstat(fp->_file, &st))
 			goto dumb;
 		if (offset > 0 && st.st_size > OFF_MAX - offset) {
 			errno = EOVERFLOW;
 			return (-1);
 		}
 		target = st.st_size + offset;
 		if ((off_t)target < 0) {
 			errno = EINVAL;
 			return (-1);
 		}
 		if (ltest && (off_t)target > LONG_MAX) {
 			errno = EOVERFLOW;
 			return (-1);
 		}
 	}
 
 	if (!havepos && _ftello(fp, &curoff))
 		goto dumb;
 
 	/*
 	 * (If the buffer was modified, we have to
 	 * skip this; see fgetln.c.)
 	 */
 	if (fp->_flags & __SMOD)
 		goto abspos;
 
 	/*
 	 * Compute the number of bytes in the input buffer (pretending
 	 * that any ungetc() input has been discarded).  Adjust current
 	 * offset backwards by this count so that it represents the
 	 * file offset for the first byte in the current input buffer.
 	 */
 	if (HASUB(fp)) {
 		curoff += fp->_r;	/* kill off ungetc */
 		n = fp->_up - fp->_bf._base;
 		curoff -= n;
 		n += fp->_ur;
 	} else {
 		n = fp->_p - fp->_bf._base;
 		curoff -= n;
 		n += fp->_r;
 	}
 
 	/*
 	 * If the target offset is within the current buffer,
 	 * simply adjust the pointers, clear EOF, undo ungetc(),
 	 * and return.
 	 */
 	if (target >= curoff && target < curoff + n) {
 		size_t o = target - curoff;
 
 		fp->_p = fp->_bf._base + o;
 		fp->_r = n - o;
 		if (HASUB(fp))
 			FREEUB(fp);
 		fp->_flags &= ~__SEOF;
 		memset(&fp->_mbstate, 0, sizeof(mbstate_t));
 		return (0);
 	}
 
 abspos:
 	/*
 	 * The place we want to get to is not within the current buffer,
 	 * but we can still be kind to the kernel copyout mechanism.
 	 * By aligning the file offset to a block boundary, we can let
 	 * the kernel use the VM hardware to map pages instead of
 	 * copying bytes laboriously.  Using a block boundary also
 	 * ensures that we only read one block, rather than two.
 	 */
 	curoff = target & ~(fp->_blksize - 1);
 	if (_sseek(fp, curoff, SEEK_SET) == POS_ERR)
 		goto dumb;
 	fp->_r = 0;
 	fp->_p = fp->_bf._base;
 	if (HASUB(fp))
 		FREEUB(fp);
 	n = target - curoff;
 	if (n) {
 		if (__srefill(fp) || fp->_r < n)
 			goto dumb;
 		fp->_p += n;
 		fp->_r -= n;
 	}
 	fp->_flags &= ~__SEOF;
 	memset(&fp->_mbstate, 0, sizeof(mbstate_t));
 	return (0);
 
 	/*
 	 * We get here if we cannot optimise the seek ... just
 	 * do it.  Allow the seek function to change fp->_bf._base.
 	 */
 dumb:
 	if (__sflush(fp) ||
 	    (ret = _sseek(fp, (fpos_t)offset, whence)) == POS_ERR)
 		return (-1);
 	if (ltest && ret > LONG_MAX) {
 		fp->_flags |= __SERR;
 		errno = EOVERFLOW;
 		return (-1);
 	}
 	/* success: clear EOF indicator and discard ungetc() data */
 	if (HASUB(fp))
 		FREEUB(fp);
 	fp->_p = fp->_bf._base;
 	fp->_r = 0;
 	/* fp->_w = 0; */	/* unnecessary (I think...) */
 	fp->_flags &= ~__SEOF;
 	memset(&fp->_mbstate, 0, sizeof(mbstate_t));
 	return (0);
 }
Index: head/lib/libc/stdio/fwrite.c
===================================================================
--- head/lib/libc/stdio/fwrite.c	(revision 320471)
+++ head/lib/libc/stdio/fwrite.c	(revision 320472)
@@ -1,96 +1,96 @@
 /*-
  * Copyright (c) 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
  *
  * This code is derived from software contributed to Berkeley by
  * Chris Torek.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
 static char sccsid[] = "@(#)fwrite.c	8.1 (Berkeley) 6/4/93";
 #endif /* LIBC_SCCS and not lint */
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
 #include "namespace.h"
 #include <errno.h>
 #include <stdint.h>
 #include <stdio.h>
 #include "un-namespace.h"
 #include "local.h"
 #include "fvwrite.h"
 #include "libc_private.h"
 
 /*
  * Write `count' objects (each size `size') from memory to the given file.
  * Return the number of whole objects written.
  */
 size_t
 fwrite(const void * __restrict buf, size_t size, size_t count, FILE * __restrict fp)
 {
 	size_t n;
 	struct __suio uio;
 	struct __siov iov;
 
 	/*
 	 * ANSI and SUSv2 require a return value of 0 if size or count are 0.
 	 */
 	if ((count == 0) || (size == 0))
 		return (0);
 
 	/*
 	 * Check for integer overflow.  As an optimization, first check that
 	 * at least one of {count, size} is at least 2^16, since if both
 	 * values are less than that, their product can't possibly overflow
 	 * (size_t is always at least 32 bits on FreeBSD).
 	 */
 	if (((count | size) > 0xFFFF) &&
 	    (count > SIZE_MAX / size)) {
 		errno = EINVAL;
 		fp->_flags |= __SERR;
 		return (0);
 	}
 
 	n = count * size;
 
 	iov.iov_base = (void *)buf;
 	uio.uio_resid = iov.iov_len = n;
 	uio.uio_iov = &iov;
 	uio.uio_iovcnt = 1;
 
-	FLOCKFILE(fp);
+	FLOCKFILE_CANCELSAFE(fp);
 	ORIENT(fp, -1);
 	/*
 	 * The usual case is success (__sfvwrite returns 0);
 	 * skip the divide if this happens, since divides are
 	 * generally slow and since this occurs whenever size==0.
 	 */
 	if (__sfvwrite(fp, &uio) != 0)
 	    count = (n - uio.uio_resid) / size;
-	FUNLOCKFILE(fp);
+	FUNLOCKFILE_CANCELSAFE();
 	return (count);
 }
Index: head/lib/libc/stdio/getc.c
===================================================================
--- head/lib/libc/stdio/getc.c	(revision 320471)
+++ head/lib/libc/stdio/getc.c	(revision 320472)
@@ -1,65 +1,65 @@
 /*-
  * Copyright (c) 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
  *
  * This code is derived from software contributed to Berkeley by
  * Chris Torek.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
 static char sccsid[] = "@(#)getc.c	8.1 (Berkeley) 6/4/93";
 #endif /* LIBC_SCCS and not lint */
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
 #include "namespace.h"
 #include <stdio.h>
 #include "un-namespace.h"
 #include "libc_private.h"
 #include "local.h"
 
 #undef getc
 #undef getc_unlocked
 
 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);
 }
 
 int
 getc_unlocked(FILE *fp)
 {
 
 	return (__sgetc(fp));
 }
Index: head/lib/libc/stdio/getchar.c
===================================================================
--- head/lib/libc/stdio/getchar.c	(revision 320471)
+++ head/lib/libc/stdio/getchar.c	(revision 320472)
@@ -1,68 +1,68 @@
 /*-
  * Copyright (c) 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
  *
  * This code is derived from software contributed to Berkeley by
  * Chris Torek.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
 static char sccsid[] = "@(#)getchar.c	8.1 (Berkeley) 6/4/93";
 #endif /* LIBC_SCCS and not lint */
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
 /*
  * A subroutine version of the macro getchar.
  */
 #include "namespace.h"
 #include <stdio.h>
 #include "un-namespace.h"
 #include "local.h"
 #include "libc_private.h"
 
 #undef getchar
 #undef getchar_unlocked
 
 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);
 }
 
 int
 getchar_unlocked(void)
 {
 
 	return (__sgetc(stdin));
 }
Index: head/lib/libc/stdio/getdelim.c
===================================================================
--- head/lib/libc/stdio/getdelim.c	(revision 320471)
+++ head/lib/libc/stdio/getdelim.c	(revision 320472)
@@ -1,160 +1,161 @@
 /*-
  * Copyright (c) 2009 David Schultz <das@FreeBSD.org>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
 
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
 #include "namespace.h"
 #include <sys/param.h>
 #include <errno.h>
 #include <limits.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include "un-namespace.h"
 
 #include "libc_private.h"
 #include "local.h"
 
 static inline size_t
 p2roundup(size_t n)
 {
 
 	if (!powerof2(n)) {
 		n--;
 		n |= n >> 1;
 		n |= n >> 2;
 		n |= n >> 4;
 		n |= n >> 8;
 		n |= n >> 16;
 #if SIZE_T_MAX > 0xffffffffU
 		n |= n >> 32;
 #endif
 		n++;
 	}
 	return (n);
 }
 
 /*
  * Expand *linep to hold len bytes (up to SSIZE_MAX + 1).
  */
 static inline int
 expandtofit(char ** __restrict linep, size_t len, size_t * __restrict capp)
 {
 	char *newline;
 	size_t newcap;
 
 	if (len > (size_t)SSIZE_MAX + 1) {
 		errno = EOVERFLOW;
 		return (-1);
 	}
 	if (len > *capp) {
 		if (len == (size_t)SSIZE_MAX + 1)	/* avoid overflow */
 			newcap = (size_t)SSIZE_MAX + 1;
 		else
 			newcap = p2roundup(len);
 		newline = realloc(*linep, newcap);
 		if (newline == NULL)
 			return (-1);
 		*capp = newcap;
 		*linep = newline;
 	}
 	return (0);
 }
 
 /*
  * Append the src buffer to the *dstp buffer. The buffers are of
  * length srclen and *dstlenp, respectively, and dst has space for
  * *dstlenp bytes. After the call, *dstlenp and *dstcapp are updated
  * appropriately, and *dstp is reallocated if needed. Returns 0 on
  * success, -1 on allocation failure.
  */
 static int
 sappend(char ** __restrict dstp, size_t * __restrict dstlenp,
 	size_t * __restrict dstcapp, char * __restrict src, size_t srclen)
 {
 
 	/* ensure room for srclen + dstlen + terminating NUL */
 	if (expandtofit(dstp, srclen + *dstlenp + 1, dstcapp))
 		return (-1);
 	memcpy(*dstp + *dstlenp, src, srclen);
 	*dstlenp += srclen;
 	return (0);
 }
 
 ssize_t
 getdelim(char ** __restrict linep, size_t * __restrict linecapp, int delim,
 	 FILE * __restrict fp)
 {
 	u_char *endp;
 	size_t linelen;
 
-	FLOCKFILE(fp);
+	FLOCKFILE_CANCELSAFE(fp);
 	ORIENT(fp, -1);
 
 	if (linep == NULL || linecapp == NULL) {
 		errno = EINVAL;
 		goto error;
 	}
 
 	if (*linep == NULL)
 		*linecapp = 0;
 
 	if (fp->_r <= 0 && __srefill(fp)) {
 		/* 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;
 	while ((endp = memchr(fp->_p, delim, fp->_r)) == NULL) {
 		if (sappend(linep, &linelen, linecapp, fp->_p, fp->_r))
 			goto error;
 		if (__srefill(fp)) {
 			if (!__sfeof(fp))
 				goto error;
 			goto done;	/* hit EOF */
 		}
 	}
 	endp++;	/* snarf the delimiter, too */
 	if (sappend(linep, &linelen, linecapp, fp->_p, endp - fp->_p))
 		goto error;
 	fp->_r -= endp - fp->_p;
 	fp->_p = endp;
 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;
 }
Index: head/lib/libc/stdio/gets.c
===================================================================
--- head/lib/libc/stdio/gets.c	(revision 320471)
+++ head/lib/libc/stdio/gets.c	(revision 320472)
@@ -1,76 +1,79 @@
 /*-
  * Copyright (c) 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
  *
  * This code is derived from software contributed to Berkeley by
  * Chris Torek.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
 static char sccsid[] = "@(#)gets.c	8.1 (Berkeley) 6/4/93";
 #endif /* LIBC_SCCS and not lint */
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
 #include "namespace.h"
 #include <unistd.h>
 #include <stdio.h>
 #include <sys/cdefs.h>
 #include "un-namespace.h"
 #include "libc_private.h"
 #include "local.h"
 
 __warn_references(gets, "warning: this program uses gets(), which is unsafe.");
 
 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);
 }
Index: head/lib/libc/stdio/local.h
===================================================================
--- head/lib/libc/stdio/local.h	(revision 320471)
+++ head/lib/libc/stdio/local.h	(revision 320472)
@@ -1,140 +1,166 @@
 /*-
  * Copyright (c) 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
  *
  * This code is derived from software contributed to Berkeley by
  * Chris Torek.
  *
  * Copyright (c) 2011 The FreeBSD Foundation
  * All rights reserved.
  * Portions of this software were developed by David Chisnall
  * under sponsorship from the FreeBSD Foundation.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
  *	@(#)local.h	8.3 (Berkeley) 7/3/94
  * $FreeBSD$
  */
 
+#ifndef _STDIO_LOCAL_H
+#define	_STDIO_LOCAL_H
+
 #include <sys/types.h>	/* for off_t */
 #include <pthread.h>
 #include <string.h>
 #include <wchar.h>
 #include <locale.h>
 
 /*
  * Information local to this implementation of stdio,
  * in particular, macros and private variables.
  */
 
 extern int	_sread(FILE *, char *, int);
 extern int	_swrite(FILE *, char const *, int);
 extern fpos_t	_sseek(FILE *, fpos_t, int);
 extern int	_ftello(FILE *, fpos_t *);
 extern int	_fseeko(FILE *, off_t, int, int);
 extern int	__fflush(FILE *fp);
 extern void	__fcloseall(void);
 extern wint_t	__fgetwc_mbs(FILE *, mbstate_t *, int *, locale_t);
 extern wint_t	__fputwc(wchar_t, FILE *, locale_t);
 extern int	__sflush(FILE *);
 extern FILE	*__sfp(void);
 extern int	__slbexpand(FILE *, size_t);
 extern int	__srefill(FILE *);
 extern int	__sread(void *, char *, int);
 extern int	__swrite(void *, char const *, int);
 extern fpos_t	__sseek(void *, fpos_t, int);
 extern int	__sclose(void *);
 extern void	__sinit(void);
 extern void	_cleanup(void);
 extern void	__smakebuf(FILE *);
 extern int	__swhatbuf(FILE *, size_t *, int *);
 extern int	_fwalk(int (*)(FILE *));
 extern int	__svfscanf(FILE *, locale_t, const char *, __va_list);
 extern int	__swsetup(FILE *);
 extern int	__sflags(const char *, int *);
 extern int	__ungetc(int, FILE *);
 extern wint_t	__ungetwc(wint_t, FILE *, locale_t);
 extern int	__vfprintf(FILE *, locale_t, const char *, __va_list);
 extern int	__vfscanf(FILE *, const char *, __va_list);
 extern int	__vfwprintf(FILE *, locale_t, const wchar_t *, __va_list);
 extern int	__vfwscanf(FILE * __restrict, locale_t, const wchar_t * __restrict,
 		    __va_list);
 extern size_t	__fread(void * __restrict buf, size_t size, size_t count,
 		FILE * __restrict fp);
 extern int	__sdidinit;
 
 static inline wint_t
 __fgetwc(FILE *fp, locale_t locale)
 {
 	int nread;
 
 	return (__fgetwc_mbs(fp, &fp->_mbstate, &nread, locale));
 }
 
 /*
  * Prepare the given FILE for writing, and return 0 iff it
  * can be written now.  Otherwise, return EOF and set errno.
  */
 #define	prepwrite(fp) \
  	((((fp)->_flags & __SWR) == 0 || \
  	    ((fp)->_bf._base == NULL && ((fp)->_flags & __SSTR) == 0)) && \
 	 __swsetup(fp))
 
 /*
  * Test whether the given stdio file has an active ungetc buffer;
  * release such a buffer, without restoring ordinary unread data.
  */
 #define	HASUB(fp) ((fp)->_ub._base != NULL)
 #define	FREEUB(fp) { \
 	if ((fp)->_ub._base != (fp)->_ubuf) \
 		free((char *)(fp)->_ub._base); \
 	(fp)->_ub._base = NULL; \
 }
 
 /*
  * test for an fgetln() buffer.
  */
 #define	HASLB(fp) ((fp)->_lb._base != NULL)
 #define	FREELB(fp) { \
 	free((char *)(fp)->_lb._base); \
 	(fp)->_lb._base = NULL; \
 }
 
 /*
  * Structure initializations for 'fake' FILE objects.
  */
 #define	FAKE_FILE {				\
 	._file = -1,				\
 	._fl_mutex = PTHREAD_MUTEX_INITIALIZER, \
 }
 
 /*
  * Set the orientation for a stream. If o > 0, the stream has wide-
  * orientation. If o < 0, the stream has byte-orientation.
  */
 #define	ORIENT(fp, o)	do {				\
 	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 */
Index: head/lib/libc/stdio/perror.c
===================================================================
--- head/lib/libc/stdio/perror.c	(revision 320471)
+++ head/lib/libc/stdio/perror.c	(revision 320472)
@@ -1,75 +1,75 @@
 /*
  * Copyright (c) 1988, 1993
  *	The Regents of the University of California.  All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
 static char sccsid[] = "@(#)perror.c	8.1 (Berkeley) 6/4/93";
 #endif /* LIBC_SCCS and not lint */
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
 #include "namespace.h"
 #include <sys/types.h>
 #include <sys/uio.h>
 #include <unistd.h>
 #include <errno.h>
 #include <limits.h>
 #include <stdio.h>
 #include <string.h>
 #include "un-namespace.h"
 #include "libc_private.h"
 #include "local.h"
 
 void
 perror(const char *s)
 {
 	char msgbuf[NL_TEXTMAX];
 	struct iovec *v;
 	struct iovec iov[4];
 
 	v = iov;
 	if (s != NULL && *s != '\0') {
 		v->iov_base = (char *)s;
 		v->iov_len = strlen(s);
 		v++;
 		v->iov_base = ": ";
 		v->iov_len = 2;
 		v++;
 	}
 	strerror_r(errno, msgbuf, sizeof(msgbuf));
 	v->iov_base = msgbuf;
 	v->iov_len = strlen(v->iov_base);
 	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();
 }
Index: head/lib/libc/stdio/putc.c
===================================================================
--- head/lib/libc/stdio/putc.c	(revision 320471)
+++ head/lib/libc/stdio/putc.c	(revision 320472)
@@ -1,65 +1,65 @@
 /*-
  * Copyright (c) 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
  *
  * This code is derived from software contributed to Berkeley by
  * Chris Torek.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
 static char sccsid[] = "@(#)putc.c	8.1 (Berkeley) 6/4/93";
 #endif /* LIBC_SCCS and not lint */
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
 #include "namespace.h"
 #include <stdio.h>
 #include "un-namespace.h"
 #include "local.h"
 #include "libc_private.h"
 
 #undef putc
 #undef putc_unlocked
 
 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);
 }
 
 int
 putc_unlocked(int ch, FILE *fp)
 {
 
 	return (__sputc(ch, fp));
 }
Index: head/lib/libc/stdio/putchar.c
===================================================================
--- head/lib/libc/stdio/putchar.c	(revision 320471)
+++ head/lib/libc/stdio/putchar.c	(revision 320472)
@@ -1,70 +1,70 @@
 /*-
  * Copyright (c) 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
  *
  * This code is derived from software contributed to Berkeley by
  * Chris Torek.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
 static char sccsid[] = "@(#)putchar.c	8.1 (Berkeley) 6/4/93";
 #endif /* LIBC_SCCS and not lint */
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
 #include "namespace.h"
 #include <stdio.h>
 #include "un-namespace.h"
 #include "local.h"
 #include "libc_private.h"
 
 #undef putchar
 #undef putchar_unlocked
 
 /*
  * A subroutine version of the macro putchar
  */
 int
 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);
 }
 
 int
 putchar_unlocked(int ch)
 {
 
 	return (__sputc(ch, stdout));
 }
Index: head/lib/libc/stdio/puts.c
===================================================================
--- head/lib/libc/stdio/puts.c	(revision 320471)
+++ head/lib/libc/stdio/puts.c	(revision 320472)
@@ -1,70 +1,70 @@
 /*-
  * Copyright (c) 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
  *
  * This code is derived from software contributed to Berkeley by
  * Chris Torek.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
 static char sccsid[] = "@(#)puts.c	8.1 (Berkeley) 6/4/93";
 #endif /* LIBC_SCCS and not lint */
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
 #include "namespace.h"
 #include <stdio.h>
 #include <string.h>
 #include "un-namespace.h"
 #include "fvwrite.h"
 #include "libc_private.h"
 #include "local.h"
 
 /*
  * Write the given string to stdout, appending a newline.
  */
 int
 puts(char const *s)
 {
 	int retval;
 	size_t c;
 	struct __suio uio;
 	struct __siov iov[2];
 
 	iov[0].iov_base = (void *)s;
 	iov[0].iov_len = c = strlen(s);
 	iov[1].iov_base = "\n";
 	iov[1].iov_len = 1;
 	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);
 }
Index: head/lib/libc/stdio/putw.c
===================================================================
--- head/lib/libc/stdio/putw.c	(revision 320471)
+++ head/lib/libc/stdio/putw.c	(revision 320472)
@@ -1,60 +1,61 @@
 /*-
  * Copyright (c) 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
  *
  * This code is derived from software contributed to Berkeley by
  * Chris Torek.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
 static char sccsid[] = "@(#)putw.c	8.1 (Berkeley) 6/4/93";
 #endif /* LIBC_SCCS and not lint */
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
 #include "namespace.h"
 #include <stdio.h>
 #include "un-namespace.h"
 #include "fvwrite.h"
 #include "libc_private.h"
+#include "local.h"
 
 int
 putw(int w, FILE *fp)
 {
 	int retval;
 	struct __suio uio;
 	struct __siov iov;
 
 	iov.iov_base = &w;
 	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);
 }
Index: head/lib/libc/stdio/refill.c
===================================================================
--- head/lib/libc/stdio/refill.c	(revision 320471)
+++ head/lib/libc/stdio/refill.c	(revision 320472)
@@ -1,146 +1,146 @@
 /*-
  * Copyright (c) 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
  *
  * This code is derived from software contributed to Berkeley by
  * Chris Torek.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
 static char sccsid[] = "@(#)refill.c	8.1 (Berkeley) 6/4/93";
 #endif /* LIBC_SCCS and not lint */
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
 #include "namespace.h"
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include "un-namespace.h"
 
 #include "libc_private.h"
 #include "local.h"
 
 static int lflush(FILE *);
 
 static int
 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);
 }
 
 /*
  * Refill a stdio buffer.
  * Return EOF on eof or error, 0 otherwise.
  */
 int
 __srefill(FILE *fp)
 {
 
 	/* make sure stdio is set up */
 	if (!__sdidinit)
 		__sinit();
 
 	ORIENT(fp, -1);
 
 	fp->_r = 0;		/* largely a convenience for callers */
 
 	/* SysV does not make this test; take it out for compatibility */
 	if (fp->_flags & __SEOF)
 		return (EOF);
 
 	/* if not already reading, have to be reading and writing */
 	if ((fp->_flags & __SRD) == 0) {
 		if ((fp->_flags & __SRW) == 0) {
 			errno = EBADF;
 			fp->_flags |= __SERR;
 			return (EOF);
 		}
 		/* switch to reading */
 		if (fp->_flags & __SWR) {
 			if (__sflush(fp))
 				return (EOF);
 			fp->_flags &= ~__SWR;
 			fp->_w = 0;
 			fp->_lbfsize = 0;
 		}
 		fp->_flags |= __SRD;
 	} else {
 		/*
 		 * We were reading.  If there is an ungetc buffer,
 		 * we must have been reading from that.  Drop it,
 		 * restoring the previous buffer (if any).  If there
 		 * is anything in that buffer, return.
 		 */
 		if (HASUB(fp)) {
 			FREEUB(fp);
 			if ((fp->_r = fp->_ur) != 0) {
 				fp->_p = fp->_up;
 				return (0);
 			}
 		}
 	}
 
 	if (fp->_bf._base == NULL)
 		__smakebuf(fp);
 
 	/*
 	 * Before reading from a line buffered or unbuffered file,
 	 * flush all line buffered output files, per the ANSI C
 	 * standard.
 	 */
 	if (fp->_flags & (__SLBF|__SNBF)) {
 		/* Ignore this file in _fwalk to avoid potential deadlock. */
 		fp->_flags |= __SIGN;
 		(void) _fwalk(lflush);
 		fp->_flags &= ~__SIGN;
 
 		/* Now flush this file without locking it. */
 		if ((fp->_flags & (__SLBF|__SWR)) == (__SLBF|__SWR))
 			__sflush(fp);
 	}
 	fp->_p = fp->_bf._base;
 	fp->_r = _sread(fp, (char *)fp->_p, fp->_bf._size);
 	fp->_flags &= ~__SMOD;	/* buffer contents are again pristine */
 	if (fp->_r <= 0) {
 		if (fp->_r == 0)
 			fp->_flags |= __SEOF;
 		else {
 			fp->_r = 0;
 			fp->_flags |= __SERR;
 		}
 		return (EOF);
 	}
 	return (0);
 }
Index: head/lib/libc/stdio/scanf.c
===================================================================
--- head/lib/libc/stdio/scanf.c	(revision 320471)
+++ head/lib/libc/stdio/scanf.c	(revision 320472)
@@ -1,78 +1,78 @@
 /*-
  * Copyright (c) 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
  *
  * This code is derived from software contributed to Berkeley by
  * Chris Torek.
  *
  * Copyright (c) 2011 The FreeBSD Foundation
  * All rights reserved.
  * Portions of this software were developed by David Chisnall
  * under sponsorship from the FreeBSD Foundation.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
 static char sccsid[] = "@(#)scanf.c	8.1 (Berkeley) 6/4/93";
 #endif /* LIBC_SCCS and not lint */
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
 #include "namespace.h"
 #include <stdio.h>
 #include <stdarg.h>
 #include "un-namespace.h"
 #include "libc_private.h"
 #include "local.h"
 #include "xlocale_private.h"
 
 int
 scanf(char const * __restrict fmt, ...)
 {
 	int ret;
 	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);
 }
 int
 scanf_l(locale_t locale, char const * __restrict fmt, ...)
 {
 	int ret;
 	va_list ap;
 	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);
 }
Index: head/lib/libc/stdio/setvbuf.c
===================================================================
--- head/lib/libc/stdio/setvbuf.c	(revision 320471)
+++ head/lib/libc/stdio/setvbuf.c	(revision 320472)
@@ -1,161 +1,161 @@
 /*-
  * Copyright (c) 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
  *
  * This code is derived from software contributed to Berkeley by
  * Chris Torek.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
 static char sccsid[] = "@(#)setvbuf.c	8.2 (Berkeley) 11/16/93";
 #endif /* LIBC_SCCS and not lint */
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
 #include "namespace.h"
 #include <stdio.h>
 #include <stdlib.h>
 #include "un-namespace.h"
 #include "local.h"
 #include "libc_private.h"
 
 /*
  * Set one of the three kinds of buffering, optionally including
  * a buffer.
  */
 int
 setvbuf(FILE * __restrict fp, char * __restrict buf, int mode, size_t size)
 {
 	int ret, flags;
 	size_t iosize;
 	int ttyflag;
 
 	/*
 	 * Verify arguments.  The `int' limit on `size' is due to this
 	 * particular implementation.  Note, buf and size are ignored
 	 * when setting _IONBF.
 	 */
 	if (mode != _IONBF)
 		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
 	 * malloc()ed.  We also clear any eof condition, as if this were
 	 * a seek.
 	 */
 	ret = 0;
 	(void)__sflush(fp);
 	if (HASUB(fp))
 		FREEUB(fp);
 	fp->_r = fp->_lbfsize = 0;
 	flags = fp->_flags;
 	if (flags & __SMBF)
 		free((void *)fp->_bf._base);
 	flags &= ~(__SLBF | __SNBF | __SMBF | __SOPT | __SOFF | __SNPT | __SEOF);
 
 	/* If setting unbuffered mode, skip all the hard work. */
 	if (mode == _IONBF)
 		goto nbf;
 
 	/*
 	 * Find optimal I/O size for seek optimization.  This also returns
 	 * a `tty flag' to suggest that we check isatty(fd), but we do not
 	 * care since our caller told us how to buffer.
 	 */
 	flags |= __swhatbuf(fp, &iosize, &ttyflag);
 	if (size == 0) {
 		buf = NULL;	/* force local allocation */
 		size = iosize;
 	}
 
 	/* Allocate buffer if needed. */
 	if (buf == NULL) {
 		if ((buf = malloc(size)) == NULL) {
 			/*
 			 * Unable to honor user's request.  We will return
 			 * failure, but try again with file system size.
 			 */
 			ret = EOF;
 			if (size != iosize) {
 				size = iosize;
 				buf = malloc(size);
 			}
 		}
 		if (buf == NULL) {
 			/* No luck; switch to unbuffered I/O. */
 nbf:
 			fp->_flags = flags | __SNBF;
 			fp->_w = 0;
 			fp->_bf._base = fp->_p = fp->_nbuf;
 			fp->_bf._size = 1;
-			FUNLOCKFILE(fp);
-			return (ret);
+			goto end;
 		}
 		flags |= __SMBF;
 	}
 
 	/*
 	 * Kill any seek optimization if the buffer is not the
 	 * right size.
 	 *
 	 * SHOULD WE ALLOW MULTIPLES HERE (i.e., ok iff (size % iosize) == 0)?
 	 */
 	if (size != iosize)
 		flags |= __SNPT;
 
 	/*
 	 * Fix up the FILE fields, and set __cleanup for output flush on
 	 * exit (since we are buffered in some way).
 	 */
 	if (mode == _IOLBF)
 		flags |= __SLBF;
 	fp->_flags = flags;
 	fp->_bf._base = fp->_p = (unsigned char *)buf;
 	fp->_bf._size = size;
 	/* fp->_lbfsize is still 0 */
 	if (flags & __SWR) {
 		/*
 		 * Begin or continue writing: see __swsetup().  Note
 		 * that __SNBF is impossible (it was handled earlier).
 		 */
 		if (flags & __SLBF) {
 			fp->_w = 0;
 			fp->_lbfsize = -fp->_bf._size;
 		} else
 			fp->_w = size;
 	} else {
 		/* begin/continue reading, or stay in intermediate state */
 		fp->_w = 0;
 	}
 	__cleanup = _cleanup;
 
-	FUNLOCKFILE(fp);
+end:
+	FUNLOCKFILE_CANCELSAFE();
 	return (ret);
 }
Index: head/lib/libc/stdio/stdio.c
===================================================================
--- head/lib/libc/stdio/stdio.c	(revision 320471)
+++ head/lib/libc/stdio/stdio.c	(revision 320472)
@@ -1,168 +1,176 @@
 /*-
  * Copyright (c) 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
  *
  * This code is derived from software contributed to Berkeley by
  * Chris Torek.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
 static char sccsid[] = "@(#)stdio.c	8.1 (Berkeley) 6/4/93";
 #endif /* LIBC_SCCS and not lint */
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
 #include "namespace.h"
 #include <errno.h>
 #include <fcntl.h>
 #include <limits.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include "un-namespace.h"
 #include "local.h"
 
 /*
  * Small standard I/O/seek/close functions.
  */
 int
 __sread(void *cookie, char *buf, int n)
 {
 	FILE *fp = cookie;
 
 	return(_read(fp->_file, buf, (size_t)n));
 }
 
 int
 __swrite(void *cookie, char const *buf, int n)
 {
 	FILE *fp = cookie;
 
 	return (_write(fp->_file, buf, (size_t)n));
 }
 
 fpos_t
 __sseek(void *cookie, fpos_t offset, int whence)
 {
 	FILE *fp = cookie;
 
 	return (lseek(fp->_file, (off_t)offset, whence));
 }
 
 int
 __sclose(void *cookie)
 {
 
 	return (_close(((FILE *)cookie)->_file));
 }
 
 /*
  * Higher level wrappers.
  */
 int
 _sread(FILE *fp, char *buf, int n)
 {
 	int ret;
 
 	ret = (*fp->_read)(fp->_cookie, buf, n);
 	if (ret > 0) {
 		if (fp->_flags & __SOFF) {
 			if (fp->_offset <= OFF_MAX - ret)
 				fp->_offset += ret;
 			else
 				fp->_flags &= ~__SOFF;
 		}
 	} else if (ret < 0)
 		fp->_flags &= ~__SOFF;
 	return (ret);
 }
 
 int
 _swrite(FILE *fp, char const *buf, int n)
 {
 	int ret;
 	int serrno;
 
 	if (fp->_flags & __SAPP) {
 		serrno = errno;
 		if (_sseek(fp, (fpos_t)0, SEEK_END) == -1 &&
 		    (fp->_flags & __SOPT))
 			return (-1);
 		errno = serrno;
 	}
 	ret = (*fp->_write)(fp->_cookie, buf, n);
 	/* __SOFF removed even on success in case O_APPEND mode is set. */
 	if (ret >= 0) {
 		if ((fp->_flags & __SOFF) && !(fp->_flags2 & __S2OAP) &&
 		    fp->_offset <= OFF_MAX - ret)
 			fp->_offset += ret;
 		else
 			fp->_flags &= ~__SOFF;
 
 	} else if (ret < 0)
 		fp->_flags &= ~__SOFF;
 	return (ret);
 }
 
 fpos_t
 _sseek(FILE *fp, fpos_t offset, int whence)
 {
 	fpos_t ret;
 	int serrno, errret;
 
 	serrno = errno;
 	errno = 0;
 	ret = (*fp->_seek)(fp->_cookie, offset, whence);
 	errret = errno;
 	if (errno == 0)
 		errno = serrno;
 	/*
 	 * Disallow negative seeks per POSIX.
 	 * It is needed here to help upper level caller
 	 * in the cases it can't detect.
 	 */
 	if (ret < 0) {
 		if (errret == 0) {
 			if (offset != 0 || whence != SEEK_CUR) {
 				if (HASUB(fp))
 					FREEUB(fp);
 				fp->_p = fp->_bf._base;
 				fp->_r = 0;
 				fp->_flags &= ~__SEOF;
 			}
 			fp->_flags |= __SERR;
 			errno = EINVAL;
 		} else if (errret == ESPIPE)
 			fp->_flags &= ~__SAPP;
 		fp->_flags &= ~__SOFF;
 		ret = -1;
 	} else if (fp->_flags & __SOPT) {
 		fp->_flags |= __SOFF;
 		fp->_offset = ret;
 	}
 	return (ret);
 }
+
+void
+__stdio_cancel_cleanup(void * arg)
+{
+
+	if (arg != NULL)
+		_funlockfile((FILE *)arg);
+}
Index: head/lib/libc/stdio/ungetc.c
===================================================================
--- head/lib/libc/stdio/ungetc.c	(revision 320471)
+++ head/lib/libc/stdio/ungetc.c	(revision 320472)
@@ -1,168 +1,168 @@
 /*-
  * Copyright (c) 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
  *
  * This code is derived from software contributed to Berkeley by
  * Chris Torek.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
 static char sccsid[] = "@(#)ungetc.c	8.2 (Berkeley) 11/3/93";
 #endif /* LIBC_SCCS and not lint */
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
 #include "namespace.h"
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include "un-namespace.h"
 #include "local.h"
 #include "libc_private.h"
 
 static int __submore(FILE *);
 
 /*
  * Expand the ungetc buffer `in place'.  That is, adjust fp->_p when
  * the buffer moves, so that it points the same distance from the end,
  * and move the bytes in the buffer around as necessary so that they
  * are all at the end (stack-style).
  */
 static int
 __submore(FILE *fp)
 {
 	int i;
 	unsigned char *p;
 
 	if (fp->_ub._base == fp->_ubuf) {
 		/*
 		 * Get a new buffer (rather than expanding the old one).
 		 */
 		if ((p = malloc((size_t)BUFSIZ)) == NULL)
 			return (EOF);
 		fp->_ub._base = p;
 		fp->_ub._size = BUFSIZ;
 		p += BUFSIZ - sizeof(fp->_ubuf);
 		for (i = sizeof(fp->_ubuf); --i >= 0;)
 			p[i] = fp->_ubuf[i];
 		fp->_p = p;
 		return (0);
 	}
 	i = fp->_ub._size;
 	p = reallocarray(fp->_ub._base, i, 2);
 	if (p == NULL)
 		return (EOF);
 	/* no overlap (hence can use memcpy) because we doubled the size */
 	(void)memcpy((void *)(p + i), (void *)p, (size_t)i);
 	fp->_p = p + i;
 	fp->_ub._base = p;
 	fp->_ub._size = i * 2;
 	return (0);
 }
 
 /*
  * MT-safe version
  */
 int
 ungetc(int c, FILE *fp)
 {
 	int ret;
 
 	if (!__sdidinit)
 		__sinit();
-	FLOCKFILE(fp);
+	FLOCKFILE_CANCELSAFE(fp);
 	ORIENT(fp, -1);
 	ret = __ungetc(c, fp);
-	FUNLOCKFILE(fp);
+	FUNLOCKFILE_CANCELSAFE();
 	return (ret);
 }
 
 /*
  * Non-MT-safe version
  */
 int
 __ungetc(int c, FILE *fp)
 {
 
 	if (c == EOF)
 		return (EOF);
 	if ((fp->_flags & __SRD) == 0) {
 		/*
 		 * Not already reading: no good unless reading-and-writing.
 		 * Otherwise, flush any current write stuff.
 		 */
 		if ((fp->_flags & __SRW) == 0)
 			return (EOF);
 		if (fp->_flags & __SWR) {
 			if (__sflush(fp))
 				return (EOF);
 			fp->_flags &= ~__SWR;
 			fp->_w = 0;
 			fp->_lbfsize = 0;
 		}
 		fp->_flags |= __SRD;
 	}
 	c = (unsigned char)c;
 
 	/*
 	 * If we are in the middle of ungetc'ing, just continue.
 	 * This may require expanding the current ungetc buffer.
 	 */
 	if (HASUB(fp)) {
 		if (fp->_r >= fp->_ub._size && __submore(fp))
 			return (EOF);
 		*--fp->_p = c;
 		fp->_r++;
 		return (c);
 	}
 	fp->_flags &= ~__SEOF;
 
 	/*
 	 * If we can handle this by simply backing up, do so,
 	 * but never replace the original character.
 	 * (This makes sscanf() work when scanning `const' data.)
 	 */
 	if (fp->_bf._base != NULL && fp->_p > fp->_bf._base &&
 	    fp->_p[-1] == c) {
 		fp->_p--;
 		fp->_r++;
 		return (c);
 	}
 
 	/*
 	 * Create an ungetc buffer.
 	 * Initially, we will use the `reserve' buffer.
 	 */
 	fp->_ur = fp->_r;
 	fp->_up = fp->_p;
 	fp->_ub._base = fp->_ubuf;
 	fp->_ub._size = sizeof(fp->_ubuf);
 	fp->_ubuf[sizeof(fp->_ubuf) - 1] = c;
 	fp->_p = &fp->_ubuf[sizeof(fp->_ubuf) - 1];
 	fp->_r = 1;
 	return (c);
 }
Index: head/lib/libc/stdio/ungetwc.c
===================================================================
--- head/lib/libc/stdio/ungetwc.c	(revision 320471)
+++ head/lib/libc/stdio/ungetwc.c	(revision 320472)
@@ -1,90 +1,90 @@
 /*-
  * Copyright (c) 2002-2004 Tim J. Robbins.
  * All rights reserved.
  *
  * Copyright (c) 2011 The FreeBSD Foundation
  * All rights reserved.
  * Portions of this software were developed by David Chisnall
  * under sponsorship from the FreeBSD Foundation.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  *
  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
 
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
 #include "namespace.h"
 #include <errno.h>
 #include <limits.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <wchar.h>
 #include "un-namespace.h"
 #include "libc_private.h"
 #include "local.h"
 #include "mblocal.h"
 #include "xlocale_private.h"
 
 /*
  * Non-MT-safe version.
  */
 wint_t
 __ungetwc(wint_t wc, FILE *fp, locale_t locale)
 {
 	char buf[MB_LEN_MAX];
 	size_t len;
 	struct xlocale_ctype *l = XLOCALE_CTYPE(locale);
 
 	if (wc == WEOF)
 		return (WEOF);
 	if ((len = l->__wcrtomb(buf, wc, &fp->_mbstate)) == (size_t)-1) {
 		fp->_flags |= __SERR;
 		return (WEOF);
 	}
 	while (len-- != 0)
 		if (__ungetc((unsigned char)buf[len], fp) == EOF)
 			return (WEOF);
 
 	return (wc);
 }
 
 /*
  * MT-safe version.
  */
 wint_t
 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);
 }
 wint_t
 ungetwc(wint_t wc, FILE *fp)
 {
 	return ungetwc_l(wc, fp, __get_locale());
 }
Index: head/lib/libc/stdio/vfprintf.c
===================================================================
--- head/lib/libc/stdio/vfprintf.c	(revision 320471)
+++ head/lib/libc/stdio/vfprintf.c	(revision 320472)
@@ -1,1045 +1,1045 @@
 /*-
  * Copyright (c) 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
  *
  * This code is derived from software contributed to Berkeley by
  * Chris Torek.
  *
  * Copyright (c) 2011 The FreeBSD Foundation
  * All rights reserved.
  * Portions of this software were developed by David Chisnall
  * under sponsorship from the FreeBSD Foundation.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
 static char sccsid[] = "@(#)vfprintf.c	8.1 (Berkeley) 6/4/93";
 #endif /* LIBC_SCCS and not lint */
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
 /*
  * Actual printf innards.
  *
  * This code is large and complicated...
  */
 
 #include "namespace.h"
 #include <sys/types.h>
 
 #include <ctype.h>
 #include <errno.h>
 #include <limits.h>
 #include <locale.h>
 #include <stddef.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <wchar.h>
 #include <printf.h>
 
 #include <stdarg.h>
 #include "xlocale_private.h"
 #include "un-namespace.h"
 
 #include "libc_private.h"
 #include "local.h"
 #include "fvwrite.h"
 #include "printflocal.h"
 
 static int	__sprint(FILE *, struct __suio *, locale_t);
 static int	__sbprintf(FILE *, locale_t, const char *, va_list) __printflike(3, 0)
 	__noinline;
 static char	*__wcsconv(wchar_t *, int);
 
 #define	CHAR	char
 #include "printfcommon.h"
 
 struct grouping_state {
 	char *thousands_sep;	/* locale-specific thousands separator */
 	int thousep_len;	/* length of thousands_sep */
 	const char *grouping;	/* locale-specific numeric grouping rules */
 	int lead;		/* sig figs before decimal or group sep */
 	int nseps;		/* number of group separators with ' */
 	int nrepeats;		/* number of repeats of the last group */
 };
 
 /*
  * Initialize the thousands' grouping state in preparation to print a
  * number with ndigits digits. This routine returns the total number
  * of bytes that will be needed.
  */
 static int
 grouping_init(struct grouping_state *gs, int ndigits, locale_t loc)
 {
 	struct lconv *locale;
 
 	locale = localeconv_l(loc);
 	gs->grouping = locale->grouping;
 	gs->thousands_sep = locale->thousands_sep;
 	gs->thousep_len = strlen(gs->thousands_sep);
 
 	gs->nseps = gs->nrepeats = 0;
 	gs->lead = ndigits;
 	while (*gs->grouping != CHAR_MAX) {
 		if (gs->lead <= *gs->grouping)
 			break;
 		gs->lead -= *gs->grouping;
 		if (*(gs->grouping+1)) {
 			gs->nseps++;
 			gs->grouping++;
 		} else
 			gs->nrepeats++;
 	}
 	return ((gs->nseps + gs->nrepeats) * gs->thousep_len);
 }
 
 /*
  * Print a number with thousands' separators.
  */
 static int
 grouping_print(struct grouping_state *gs, struct io_state *iop,
 	       const CHAR *cp, const CHAR *ep, locale_t locale)
 {
 	const CHAR *cp0 = cp;
 
 	if (io_printandpad(iop, cp, ep, gs->lead, zeroes, locale))
 		return (-1);
 	cp += gs->lead;
 	while (gs->nseps > 0 || gs->nrepeats > 0) {
 		if (gs->nrepeats > 0)
 			gs->nrepeats--;
 		else {
 			gs->grouping--;
 			gs->nseps--;
 		}
 		if (io_print(iop, gs->thousands_sep, gs->thousep_len, locale))
 			return (-1);
 		if (io_printandpad(iop, cp, ep, *gs->grouping, zeroes, locale))
 			return (-1);
 		cp += *gs->grouping;
 	}
 	if (cp > ep)
 		cp = ep;
 	return (cp - cp0);
 }
 
 /*
  * Flush out all the vectors defined by the given uio,
  * then reset it so that it can be reused.
  */
 static int
 __sprint(FILE *fp, struct __suio *uio, locale_t locale)
 {
 	int err;
 
 	if (uio->uio_resid == 0) {
 		uio->uio_iovcnt = 0;
 		return (0);
 	}
 	err = __sfvwrite(fp, uio);
 	uio->uio_resid = 0;
 	uio->uio_iovcnt = 0;
 	return (err);
 }
 
 /*
  * Helper function for `fprintf to unbuffered unix file': creates a
  * temporary buffer.  We only work on write-only files; this avoids
  * worries about ungetc buffers and so forth.
  */
 static int
 __sbprintf(FILE *fp, locale_t locale, const char *fmt, va_list ap)
 {
 	int ret;
 	FILE fake = FAKE_FILE;
 	unsigned char buf[BUFSIZ];
 
 	/* XXX This is probably not needed. */
 	if (prepwrite(fp) != 0)
 		return (EOF);
 
 	/* copy the important variables */
 	fake._flags = fp->_flags & ~__SNBF;
 	fake._file = fp->_file;
 	fake._cookie = fp->_cookie;
 	fake._write = fp->_write;
 	fake._orientation = fp->_orientation;
 	fake._mbstate = fp->_mbstate;
 
 	/* set up the buffer */
 	fake._bf._base = fake._p = buf;
 	fake._bf._size = fake._w = sizeof(buf);
 	fake._lbfsize = 0;	/* not actually used, but Just In Case */
 
 	/* do the work, then copy any error status */
 	ret = __vfprintf(&fake, locale, fmt, ap);
 	if (ret >= 0 && __fflush(&fake))
 		ret = EOF;
 	if (fake._flags & __SERR)
 		fp->_flags |= __SERR;
 	return (ret);
 }
 
 /*
  * Convert a wide character string argument for the %ls format to a multibyte
  * string representation. If not -1, prec specifies the maximum number of
  * bytes to output, and also means that we can't assume that the wide char.
  * string ends is null-terminated.
  */
 static char *
 __wcsconv(wchar_t *wcsarg, int prec)
 {
 	static const mbstate_t initial;
 	mbstate_t mbs;
 	char buf[MB_LEN_MAX];
 	wchar_t *p;
 	char *convbuf;
 	size_t clen, nbytes;
 
 	/* Allocate space for the maximum number of bytes we could output. */
 	if (prec < 0) {
 		p = wcsarg;
 		mbs = initial;
 		nbytes = wcsrtombs(NULL, (const wchar_t **)&p, 0, &mbs);
 		if (nbytes == (size_t)-1)
 			return (NULL);
 	} else {
 		/*
 		 * Optimisation: if the output precision is small enough,
 		 * just allocate enough memory for the maximum instead of
 		 * scanning the string.
 		 */
 		if (prec < 128)
 			nbytes = prec;
 		else {
 			nbytes = 0;
 			p = wcsarg;
 			mbs = initial;
 			for (;;) {
 				clen = wcrtomb(buf, *p++, &mbs);
 				if (clen == 0 || clen == (size_t)-1 ||
 				    nbytes + clen > prec)
 					break;
 				nbytes += clen;
 			}
 		}
 	}
 	if ((convbuf = malloc(nbytes + 1)) == NULL)
 		return (NULL);
 
 	/* Fill the output buffer. */
 	p = wcsarg;
 	mbs = initial;
 	if ((nbytes = wcsrtombs(convbuf, (const wchar_t **)&p,
 	    nbytes, &mbs)) == (size_t)-1) {
 		free(convbuf);
 		return (NULL);
 	}
 	convbuf[nbytes] = '\0';
 	return (convbuf);
 }
 
 /*
  * MT-safe version
  */
 int
 vfprintf_l(FILE * __restrict fp, locale_t locale, const char * __restrict fmt0,
 		va_list ap)
 {
 	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
 vfprintf(FILE * __restrict fp, const char * __restrict fmt0, va_list ap)
 {
 	return vfprintf_l(fp, __get_locale(), fmt0, ap);
 }
 
 /*
  * The size of the buffer we use as scratch space for integer
  * conversions, among other things.  We need enough space to
  * write a uintmax_t in octal (plus one byte).
  */
 #if UINTMAX_MAX <= UINT64_MAX
 #define	BUF	32
 #else
 #error "BUF must be large enough to format a uintmax_t"
 #endif
 
 /*
  * Non-MT-safe version
  */
 int
 __vfprintf(FILE *fp, locale_t locale, const char *fmt0, va_list ap)
 {
 	char *fmt;		/* format string */
 	int ch;			/* character from fmt */
 	int n, n2;		/* handy integer (short term usage) */
 	char *cp;		/* handy char pointer (short term usage) */
 	int flags;		/* flags as above */
 	int ret;		/* return value accumulator */
 	int width;		/* width from format (%8d), or 0 */
 	int prec;		/* precision from format; <0 for N/A */
 	char sign;		/* sign prefix (' ', '+', '-', or \0) */
 	struct grouping_state gs; /* thousands' grouping info */
 
 #ifndef NO_FLOATING_POINT
 	/*
 	 * We can decompose the printed representation of floating
 	 * point numbers into several parts, some of which may be empty:
 	 *
 	 * [+|-| ] [0x|0X] MMM . NNN [e|E|p|P] [+|-] ZZ
 	 *    A       B     ---C---      D       E   F
 	 *
 	 * A:	'sign' holds this value if present; '\0' otherwise
 	 * B:	ox[1] holds the 'x' or 'X'; '\0' if not hexadecimal
 	 * C:	cp points to the string MMMNNN.  Leading and trailing
 	 *	zeros are not in the string and must be added.
 	 * D:	expchar holds this character; '\0' if no exponent, e.g. %f
 	 * F:	at least two digits for decimal, at least one digit for hex
 	 */
 	char *decimal_point;	/* locale specific decimal point */
 	int decpt_len;		/* length of decimal_point */
 	int signflag;		/* true if float is negative */
 	union {			/* floating point arguments %[aAeEfFgG] */
 		double dbl;
 		long double ldbl;
 	} fparg;
 	int expt;		/* integer value of exponent */
 	char expchar;		/* exponent character: [eEpP\0] */
 	char *dtoaend;		/* pointer to end of converted digits */
 	int expsize;		/* character count for expstr */
 	int ndig;		/* actual number of digits returned by dtoa */
 	char expstr[MAXEXPDIG+2];	/* buffer for exponent string: e+ZZZ */
 	char *dtoaresult;	/* buffer allocated by dtoa */
 #endif
 	u_long	ulval;		/* integer arguments %[diouxX] */
 	uintmax_t ujval;	/* %j, %ll, %q, %t, %z integers */
 	int base;		/* base for [diouxX] conversion */
 	int dprec;		/* a copy of prec if [diouxX], 0 otherwise */
 	int realsz;		/* field size expanded by dprec, sign, etc */
 	int size;		/* size of converted field or string */
 	int prsize;             /* max size of printed field */
 	const char *xdigs;     	/* digits for %[xX] conversion */
 	struct io_state io;	/* I/O buffering state */
 	char buf[BUF];		/* buffer with space for digits of uintmax_t */
 	char ox[2];		/* space for 0x; ox[1] is either x, X, or \0 */
 	union arg *argtable;    /* args, built due to positional arg */
 	union arg statargtable [STATIC_ARG_TBL_SIZE];
 	int nextarg;            /* 1-based argument index */
 	va_list orgap;          /* original argument pointer */
 	char *convbuf;		/* wide to multibyte conversion result */
 	int savserr;
 
 	static const char xdigs_lower[16] = "0123456789abcdef";
 	static const char xdigs_upper[16] = "0123456789ABCDEF";
 
 	/* BEWARE, these `goto error' on error. */
 #define	PRINT(ptr, len) { \
 	if (io_print(&io, (ptr), (len), locale))	\
 		goto error; \
 }
 #define	PAD(howmany, with) { \
 	if (io_pad(&io, (howmany), (with), locale)) \
 		goto error; \
 }
 #define	PRINTANDPAD(p, ep, len, with) {	\
 	if (io_printandpad(&io, (p), (ep), (len), (with), locale)) \
 		goto error; \
 }
 #define	FLUSH() { \
 	if (io_flush(&io, locale)) \
 		goto error; \
 }
 
 	/*
 	 * Get the argument indexed by nextarg.   If the argument table is
 	 * built, use it to get the argument.  If its not, get the next
 	 * argument (and arguments must be gotten sequentially).
 	 */
 #define GETARG(type) \
 	((argtable != NULL) ? *((type*)(&argtable[nextarg++])) : \
 	    (nextarg++, va_arg(ap, type)))
 
 	/*
 	 * To extend shorts properly, we need both signed and unsigned
 	 * argument extraction methods.
 	 */
 #define	SARG() \
 	(flags&LONGINT ? GETARG(long) : \
 	    flags&SHORTINT ? (long)(short)GETARG(int) : \
 	    flags&CHARINT ? (long)(signed char)GETARG(int) : \
 	    (long)GETARG(int))
 #define	UARG() \
 	(flags&LONGINT ? GETARG(u_long) : \
 	    flags&SHORTINT ? (u_long)(u_short)GETARG(int) : \
 	    flags&CHARINT ? (u_long)(u_char)GETARG(int) : \
 	    (u_long)GETARG(u_int))
 #define	INTMAX_SIZE	(INTMAXT|SIZET|PTRDIFFT|LLONGINT)
 #define SJARG() \
 	(flags&INTMAXT ? GETARG(intmax_t) : \
 	    flags&SIZET ? (intmax_t)GETARG(ssize_t) : \
 	    flags&PTRDIFFT ? (intmax_t)GETARG(ptrdiff_t) : \
 	    (intmax_t)GETARG(long long))
 #define	UJARG() \
 	(flags&INTMAXT ? GETARG(uintmax_t) : \
 	    flags&SIZET ? (uintmax_t)GETARG(size_t) : \
 	    flags&PTRDIFFT ? (uintmax_t)GETARG(ptrdiff_t) : \
 	    (uintmax_t)GETARG(unsigned long long))
 
 	/*
 	 * Get * arguments, including the form *nn$.  Preserve the nextarg
 	 * that the argument can be gotten once the type is determined.
 	 */
 #define GETASTER(val) \
 	n2 = 0; \
 	cp = fmt; \
 	while (is_digit(*cp)) { \
 		n2 = 10 * n2 + to_digit(*cp); \
 		cp++; \
 	} \
 	if (*cp == '$') { \
 		int hold = nextarg; \
 		if (argtable == NULL) { \
 			argtable = statargtable; \
 			if (__find_arguments (fmt0, orgap, &argtable)) { \
 				ret = EOF; \
 				goto error; \
 			} \
 		} \
 		nextarg = n2; \
 		val = GETARG (int); \
 		nextarg = hold; \
 		fmt = ++cp; \
 	} else { \
 		val = GETARG (int); \
 	}
 
 	if (__use_xprintf == 0 && getenv("USE_XPRINTF"))
 		__use_xprintf = 1;
 	if (__use_xprintf > 0)
 		return (__xvprintf(fp, fmt0, ap));
 
 	/* sorry, fprintf(read_only_file, "") returns EOF, not 0 */
 	if (prepwrite(fp) != 0) {
 		errno = EBADF;
 		return (EOF);
 	}
 
 	savserr = fp->_flags & __SERR;
 	fp->_flags &= ~__SERR;
 
 	convbuf = NULL;
 	fmt = (char *)fmt0;
 	argtable = NULL;
 	nextarg = 1;
 	va_copy(orgap, ap);
 	io_init(&io, fp);
 	ret = 0;
 #ifndef NO_FLOATING_POINT
 	dtoaresult = NULL;
 	decimal_point = localeconv_l(locale)->decimal_point;
 	/* The overwhelmingly common case is decpt_len == 1. */
 	decpt_len = (decimal_point[1] == '\0' ? 1 : strlen(decimal_point));
 #endif
 
 	/*
 	 * Scan the format for conversions (`%' character).
 	 */
 	for (;;) {
 		for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++)
 			/* void */;
 		if ((n = fmt - cp) != 0) {
 			if ((unsigned)ret + n > INT_MAX) {
 				ret = EOF;
 				errno = EOVERFLOW;
 				goto error;
 			}
 			PRINT(cp, n);
 			ret += n;
 		}
 		if (ch == '\0')
 			goto done;
 		fmt++;		/* skip over '%' */
 
 		flags = 0;
 		dprec = 0;
 		width = 0;
 		prec = -1;
 		gs.grouping = NULL;
 		sign = '\0';
 		ox[1] = '\0';
 
 rflag:		ch = *fmt++;
 reswitch:	switch (ch) {
 		case ' ':
 			/*-
 			 * ``If the space and + flags both appear, the space
 			 * flag will be ignored.''
 			 *	-- ANSI X3J11
 			 */
 			if (!sign)
 				sign = ' ';
 			goto rflag;
 		case '#':
 			flags |= ALT;
 			goto rflag;
 		case '*':
 			/*-
 			 * ``A negative field width argument is taken as a
 			 * - flag followed by a positive field width.''
 			 *	-- ANSI X3J11
 			 * They don't exclude field widths read from args.
 			 */
 			GETASTER (width);
 			if (width >= 0)
 				goto rflag;
 			width = -width;
 			/* FALLTHROUGH */
 		case '-':
 			flags |= LADJUST;
 			goto rflag;
 		case '+':
 			sign = '+';
 			goto rflag;
 		case '\'':
 			flags |= GROUPING;
 			goto rflag;
 		case '.':
 			if ((ch = *fmt++) == '*') {
 				GETASTER (prec);
 				goto rflag;
 			}
 			prec = 0;
 			while (is_digit(ch)) {
 				prec = 10 * prec + to_digit(ch);
 				ch = *fmt++;
 			}
 			goto reswitch;
 		case '0':
 			/*-
 			 * ``Note that 0 is taken as a flag, not as the
 			 * beginning of a field width.''
 			 *	-- ANSI X3J11
 			 */
 			flags |= ZEROPAD;
 			goto rflag;
 		case '1': case '2': case '3': case '4':
 		case '5': case '6': case '7': case '8': case '9':
 			n = 0;
 			do {
 				n = 10 * n + to_digit(ch);
 				ch = *fmt++;
 			} while (is_digit(ch));
 			if (ch == '$') {
 				nextarg = n;
 				if (argtable == NULL) {
 					argtable = statargtable;
 					if (__find_arguments (fmt0, orgap,
 							      &argtable)) {
 						ret = EOF;
 						goto error;
 					}
 				}
 				goto rflag;
 			}
 			width = n;
 			goto reswitch;
 #ifndef NO_FLOATING_POINT
 		case 'L':
 			flags |= LONGDBL;
 			goto rflag;
 #endif
 		case 'h':
 			if (flags & SHORTINT) {
 				flags &= ~SHORTINT;
 				flags |= CHARINT;
 			} else
 				flags |= SHORTINT;
 			goto rflag;
 		case 'j':
 			flags |= INTMAXT;
 			goto rflag;
 		case 'l':
 			if (flags & LONGINT) {
 				flags &= ~LONGINT;
 				flags |= LLONGINT;
 			} else
 				flags |= LONGINT;
 			goto rflag;
 		case 'q':
 			flags |= LLONGINT;	/* not necessarily */
 			goto rflag;
 		case 't':
 			flags |= PTRDIFFT;
 			goto rflag;
 		case 'z':
 			flags |= SIZET;
 			goto rflag;
 		case 'C':
 			flags |= LONGINT;
 			/*FALLTHROUGH*/
 		case 'c':
 			if (flags & LONGINT) {
 				static const mbstate_t initial;
 				mbstate_t mbs;
 				size_t mbseqlen;
 
 				mbs = initial;
 				mbseqlen = wcrtomb(cp = buf,
 				    (wchar_t)GETARG(wint_t), &mbs);
 				if (mbseqlen == (size_t)-1) {
 					fp->_flags |= __SERR;
 					goto error;
 				}
 				size = (int)mbseqlen;
 			} else {
 				*(cp = buf) = GETARG(int);
 				size = 1;
 			}
 			sign = '\0';
 			break;
 		case 'D':
 			flags |= LONGINT;
 			/*FALLTHROUGH*/
 		case 'd':
 		case 'i':
 			if (flags & INTMAX_SIZE) {
 				ujval = SJARG();
 				if ((intmax_t)ujval < 0) {
 					ujval = -ujval;
 					sign = '-';
 				}
 			} else {
 				ulval = SARG();
 				if ((long)ulval < 0) {
 					ulval = -ulval;
 					sign = '-';
 				}
 			}
 			base = 10;
 			goto number;
 #ifndef NO_FLOATING_POINT
 		case 'a':
 		case 'A':
 			if (ch == 'a') {
 				ox[1] = 'x';
 				xdigs = xdigs_lower;
 				expchar = 'p';
 			} else {
 				ox[1] = 'X';
 				xdigs = xdigs_upper;
 				expchar = 'P';
 			}
 			if (prec >= 0)
 				prec++;
 			if (dtoaresult != NULL)
 				freedtoa(dtoaresult);
 			if (flags & LONGDBL) {
 				fparg.ldbl = GETARG(long double);
 				dtoaresult = cp =
 				    __hldtoa(fparg.ldbl, xdigs, prec,
 				    &expt, &signflag, &dtoaend);
 			} else {
 				fparg.dbl = GETARG(double);
 				dtoaresult = cp =
 				    __hdtoa(fparg.dbl, xdigs, prec,
 				    &expt, &signflag, &dtoaend);
 			}
 			if (prec < 0)
 				prec = dtoaend - cp;
 			if (expt == INT_MAX)
 				ox[1] = '\0';
 			goto fp_common;
 		case 'e':
 		case 'E':
 			expchar = ch;
 			if (prec < 0)	/* account for digit before decpt */
 				prec = DEFPREC + 1;
 			else
 				prec++;
 			goto fp_begin;
 		case 'f':
 		case 'F':
 			expchar = '\0';
 			goto fp_begin;
 		case 'g':
 		case 'G':
 			expchar = ch - ('g' - 'e');
 			if (prec == 0)
 				prec = 1;
 fp_begin:
 			if (prec < 0)
 				prec = DEFPREC;
 			if (dtoaresult != NULL)
 				freedtoa(dtoaresult);
 			if (flags & LONGDBL) {
 				fparg.ldbl = GETARG(long double);
 				dtoaresult = cp =
 				    __ldtoa(&fparg.ldbl, expchar ? 2 : 3, prec,
 				    &expt, &signflag, &dtoaend);
 			} else {
 				fparg.dbl = GETARG(double);
 				dtoaresult = cp =
 				    dtoa(fparg.dbl, expchar ? 2 : 3, prec,
 				    &expt, &signflag, &dtoaend);
 				if (expt == 9999)
 					expt = INT_MAX;
 			}
 fp_common:
 			if (signflag)
 				sign = '-';
 			if (expt == INT_MAX) {	/* inf or nan */
 				if (*cp == 'N') {
 					cp = (ch >= 'a') ? "nan" : "NAN";
 					sign = '\0';
 				} else
 					cp = (ch >= 'a') ? "inf" : "INF";
 				size = 3;
 				flags &= ~ZEROPAD;
 				break;
 			}
 			flags |= FPT;
 			ndig = dtoaend - cp;
 			if (ch == 'g' || ch == 'G') {
 				if (expt > -4 && expt <= prec) {
 					/* Make %[gG] smell like %[fF] */
 					expchar = '\0';
 					if (flags & ALT)
 						prec -= expt;
 					else
 						prec = ndig - expt;
 					if (prec < 0)
 						prec = 0;
 				} else {
 					/*
 					 * Make %[gG] smell like %[eE], but
 					 * trim trailing zeroes if no # flag.
 					 */
 					if (!(flags & ALT))
 						prec = ndig;
 				}
 			}
 			if (expchar) {
 				expsize = exponent(expstr, expt - 1, expchar);
 				size = expsize + prec;
 				if (prec > 1 || flags & ALT)
 					size += decpt_len;
 			} else {
 				/* space for digits before decimal point */
 				if (expt > 0)
 					size = expt;
 				else	/* "0" */
 					size = 1;
 				/* space for decimal pt and following digits */
 				if (prec || flags & ALT)
 					size += prec + decpt_len;
 				if ((flags & GROUPING) && expt > 0)
 					size += grouping_init(&gs, expt, locale);
 			}
 			break;
 #endif /* !NO_FLOATING_POINT */
 		case 'n':
 			/*
 			 * Assignment-like behavior is specified if the
 			 * value overflows or is otherwise unrepresentable.
 			 * C99 says to use `signed char' for %hhn conversions.
 			 */
 			if (flags & LLONGINT)
 				*GETARG(long long *) = ret;
 			else if (flags & SIZET)
 				*GETARG(ssize_t *) = (ssize_t)ret;
 			else if (flags & PTRDIFFT)
 				*GETARG(ptrdiff_t *) = ret;
 			else if (flags & INTMAXT)
 				*GETARG(intmax_t *) = ret;
 			else if (flags & LONGINT)
 				*GETARG(long *) = ret;
 			else if (flags & SHORTINT)
 				*GETARG(short *) = ret;
 			else if (flags & CHARINT)
 				*GETARG(signed char *) = ret;
 			else
 				*GETARG(int *) = ret;
 			continue;	/* no output */
 		case 'O':
 			flags |= LONGINT;
 			/*FALLTHROUGH*/
 		case 'o':
 			if (flags & INTMAX_SIZE)
 				ujval = UJARG();
 			else
 				ulval = UARG();
 			base = 8;
 			goto nosign;
 		case 'p':
 			/*-
 			 * ``The argument shall be a pointer to void.  The
 			 * value of the pointer is converted to a sequence
 			 * of printable characters, in an implementation-
 			 * defined manner.''
 			 *	-- ANSI X3J11
 			 */
 			ujval = (uintmax_t)(uintptr_t)GETARG(void *);
 			base = 16;
 			xdigs = xdigs_lower;
 			flags = flags | INTMAXT;
 			ox[1] = 'x';
 			goto nosign;
 		case 'S':
 			flags |= LONGINT;
 			/*FALLTHROUGH*/
 		case 's':
 			if (flags & LONGINT) {
 				wchar_t *wcp;
 
 				if (convbuf != NULL)
 					free(convbuf);
 				if ((wcp = GETARG(wchar_t *)) == NULL)
 					cp = "(null)";
 				else {
 					convbuf = __wcsconv(wcp, prec);
 					if (convbuf == NULL) {
 						fp->_flags |= __SERR;
 						goto error;
 					}
 					cp = convbuf;
 				}
 			} else if ((cp = GETARG(char *)) == NULL)
 				cp = "(null)";
 			size = (prec >= 0) ? strnlen(cp, prec) : strlen(cp);
 			sign = '\0';
 			break;
 		case 'U':
 			flags |= LONGINT;
 			/*FALLTHROUGH*/
 		case 'u':
 			if (flags & INTMAX_SIZE)
 				ujval = UJARG();
 			else
 				ulval = UARG();
 			base = 10;
 			goto nosign;
 		case 'X':
 			xdigs = xdigs_upper;
 			goto hex;
 		case 'x':
 			xdigs = xdigs_lower;
 hex:
 			if (flags & INTMAX_SIZE)
 				ujval = UJARG();
 			else
 				ulval = UARG();
 			base = 16;
 			/* leading 0x/X only if non-zero */
 			if (flags & ALT &&
 			    (flags & INTMAX_SIZE ? ujval != 0 : ulval != 0))
 				ox[1] = ch;
 
 			flags &= ~GROUPING;
 			/* unsigned conversions */
 nosign:			sign = '\0';
 			/*-
 			 * ``... diouXx conversions ... if a precision is
 			 * specified, the 0 flag will be ignored.''
 			 *	-- ANSI X3J11
 			 */
 number:			if ((dprec = prec) >= 0)
 				flags &= ~ZEROPAD;
 
 			/*-
 			 * ``The result of converting a zero value with an
 			 * explicit precision of zero is no characters.''
 			 *	-- ANSI X3J11
 			 *
 			 * ``The C Standard is clear enough as is.  The call
 			 * printf("%#.0o", 0) should print 0.''
 			 *	-- Defect Report #151
 			 */
 			cp = buf + BUF;
 			if (flags & INTMAX_SIZE) {
 				if (ujval != 0 || prec != 0 ||
 				    (flags & ALT && base == 8))
 					cp = __ujtoa(ujval, cp, base,
 					    flags & ALT, xdigs);
 			} else {
 				if (ulval != 0 || prec != 0 ||
 				    (flags & ALT && base == 8))
 					cp = __ultoa(ulval, cp, base,
 					    flags & ALT, xdigs);
 			}
 			size = buf + BUF - cp;
 			if (size > BUF)	/* should never happen */
 				abort();
 			if ((flags & GROUPING) && size != 0)
 				size += grouping_init(&gs, size, locale);
 			break;
 		default:	/* "%?" prints ?, unless ? is NUL */
 			if (ch == '\0')
 				goto done;
 			/* pretend it was %c with argument ch */
 			cp = buf;
 			*cp = ch;
 			size = 1;
 			sign = '\0';
 			break;
 		}
 
 		/*
 		 * All reasonable formats wind up here.  At this point, `cp'
 		 * points to a string which (if not flags&LADJUST) should be
 		 * padded out to `width' places.  If flags&ZEROPAD, it should
 		 * first be prefixed by any sign or other prefix; otherwise,
 		 * it should be blank padded before the prefix is emitted.
 		 * After any left-hand padding and prefixing, emit zeroes
 		 * required by a decimal [diouxX] precision, then print the
 		 * string proper, then emit zeroes required by any leftover
 		 * floating precision; finally, if LADJUST, pad with blanks.
 		 *
 		 * Compute actual size, so we know how much to pad.
 		 * size excludes decimal prec; realsz includes it.
 		 */
 		realsz = dprec > size ? dprec : size;
 		if (sign)
 			realsz++;
 		if (ox[1])
 			realsz += 2;
 
 		prsize = width > realsz ? width : realsz;
 		if ((unsigned)ret + prsize > INT_MAX) {
 			ret = EOF;
 			errno = EOVERFLOW;
 			goto error;
 		}
 
 		/* right-adjusting blank padding */
 		if ((flags & (LADJUST|ZEROPAD)) == 0)
 			PAD(width - realsz, blanks);
 
 		/* prefix */
 		if (sign)
 			PRINT(&sign, 1);
 
 		if (ox[1]) {	/* ox[1] is either x, X, or \0 */
 			ox[0] = '0';
 			PRINT(ox, 2);
 		}
 
 		/* right-adjusting zero padding */
 		if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
 			PAD(width - realsz, zeroes);
 
 		/* the string or number proper */
 #ifndef NO_FLOATING_POINT
 		if ((flags & FPT) == 0) {
 #endif
 			/* leading zeroes from decimal precision */
 			PAD(dprec - size, zeroes);
 			if (gs.grouping) {
 				if (grouping_print(&gs, &io, cp, buf+BUF, locale) < 0)
 					goto error;
 			} else {
 				PRINT(cp, size);
 			}
 #ifndef NO_FLOATING_POINT
 		} else {	/* glue together f_p fragments */
 			if (!expchar) {	/* %[fF] or sufficiently short %[gG] */
 				if (expt <= 0) {
 					PRINT(zeroes, 1);
 					if (prec || flags & ALT)
 						PRINT(decimal_point,decpt_len);
 					PAD(-expt, zeroes);
 					/* already handled initial 0's */
 					prec += expt;
 				} else {
 					if (gs.grouping) {
 						n = grouping_print(&gs, &io,
 						    cp, dtoaend, locale);
 						if (n < 0)
 							goto error;
 						cp += n;
 					} else {
 						PRINTANDPAD(cp, dtoaend,
 						    expt, zeroes);
 						cp += expt;
 					}
 					if (prec || flags & ALT)
 						PRINT(decimal_point,decpt_len);
 				}
 				PRINTANDPAD(cp, dtoaend, prec, zeroes);
 			} else {	/* %[eE] or sufficiently long %[gG] */
 				if (prec > 1 || flags & ALT) {
 					PRINT(cp++, 1);
 					PRINT(decimal_point, decpt_len);
 					PRINT(cp, ndig-1);
 					PAD(prec - ndig, zeroes);
 				} else	/* XeYYY */
 					PRINT(cp, 1);
 				PRINT(expstr, expsize);
 			}
 		}
 #endif
 		/* left-adjusting padding (always blank) */
 		if (flags & LADJUST)
 			PAD(width - realsz, blanks);
 
 		/* finally, adjust ret */
 		ret += prsize;
 
 		FLUSH();	/* copy out the I/O vectors */
 	}
 done:
 	FLUSH();
 error:
 	va_end(orgap);
 #ifndef NO_FLOATING_POINT
 	if (dtoaresult != NULL)
 		freedtoa(dtoaresult);
 #endif
 	if (convbuf != NULL)
 		free(convbuf);
 	if (__sferror(fp))
 		ret = EOF;
 	else
 		fp->_flags |= savserr;
 	if ((argtable != NULL) && (argtable != statargtable))
 		free (argtable);
 	return (ret);
 	/* NOTREACHED */
 }
 
Index: head/lib/libc/stdio/vfscanf.c
===================================================================
--- head/lib/libc/stdio/vfscanf.c	(revision 320471)
+++ head/lib/libc/stdio/vfscanf.c	(revision 320472)
@@ -1,1092 +1,1092 @@
 /*-
  * Copyright (c) 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
  *
  * Copyright (c) 2011 The FreeBSD Foundation
  * All rights reserved.
  * Portions of this software were developed by David Chisnall
  * under sponsorship from the FreeBSD Foundation.
  *
  * This code is derived from software contributed to Berkeley by
  * Chris Torek.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
 static char sccsid[] = "@(#)vfscanf.c	8.1 (Berkeley) 6/4/93";
 #endif /* LIBC_SCCS and not lint */
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
 #include "namespace.h"
 #include <ctype.h>
 #include <inttypes.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <stddef.h>
 #include <stdarg.h>
 #include <string.h>
 #include <wchar.h>
 #include <wctype.h>
 #include "un-namespace.h"
 
 #include "collate.h"
 #include "libc_private.h"
 #include "local.h"
 #include "xlocale_private.h"
 
 #ifndef NO_FLOATING_POINT
 #include <locale.h>
 #endif
 
 #define	BUF		513	/* Maximum length of numeric string. */
 
 /*
  * Flags used during conversion.
  */
 #define	LONG		0x01	/* l: long or double */
 #define	LONGDBL		0x02	/* L: long double */
 #define	SHORT		0x04	/* h: short */
 #define	SUPPRESS	0x08	/* *: suppress assignment */
 #define	POINTER		0x10	/* p: void * (as hex) */
 #define	NOSKIP		0x20	/* [ or c: do not skip blanks */
 #define	LONGLONG	0x400	/* ll: long long (+ deprecated q: quad) */
 #define	INTMAXT		0x800	/* j: intmax_t */
 #define	PTRDIFFT	0x1000	/* t: ptrdiff_t */
 #define	SIZET		0x2000	/* z: size_t */
 #define	SHORTSHORT	0x4000	/* hh: char */
 #define	UNSIGNED	0x8000	/* %[oupxX] conversions */
 
 /*
  * The following are used in integral conversions only:
  * SIGNOK, NDIGITS, PFXOK, and NZDIGITS
  */
 #define	SIGNOK		0x40	/* +/- is (still) legal */
 #define	NDIGITS		0x80	/* no digits detected */
 #define	PFXOK		0x100	/* 0x prefix is (still) legal */
 #define	NZDIGITS	0x200	/* no zero digits detected */
 #define	HAVESIGN	0x10000	/* sign detected */
 
 /*
  * Conversion types.
  */
 #define	CT_CHAR		0	/* %c conversion */
 #define	CT_CCL		1	/* %[...] conversion */
 #define	CT_STRING	2	/* %s conversion */
 #define	CT_INT		3	/* %[dioupxX] conversion */
 #define	CT_FLOAT	4	/* %[efgEFG] conversion */
 
 static const u_char *__sccl(char *, const u_char *);
 #ifndef NO_FLOATING_POINT
 static int parsefloat(FILE *, char *, char *, locale_t);
 #endif
 
 __weak_reference(__vfscanf, vfscanf);
 
 /*
  * Conversion functions are passed a pointer to this object instead of
  * a real parameter to indicate that the assignment-suppression (*)
  * flag was specified.  We could use a NULL pointer to indicate this,
  * but that would mask bugs in applications that call scanf() with a
  * NULL pointer.
  */
 static const int suppress;
 #define	SUPPRESS_PTR	((void *)&suppress)
 
 static const mbstate_t initial_mbs;
 
 /*
  * The following conversion functions return the number of characters consumed,
  * or -1 on input failure.  Character class conversion returns 0 on match
  * failure.
  */
 
 static __inline int
 convert_char(FILE *fp, char * p, int width)
 {
 	int n;
 
 	if (p == SUPPRESS_PTR) {
 		size_t sum = 0;
 		for (;;) {
 			if ((n = fp->_r) < width) {
 				sum += n;
 				width -= n;
 				fp->_p += n;
 				if (__srefill(fp)) {
 					if (sum == 0)
 						return (-1);
 					break;
 				}
 			} else {
 				sum += width;
 				fp->_r -= width;
 				fp->_p += width;
 				break;
 			}
 		}
 		return (sum);
 	} else {
 		size_t r = __fread(p, 1, width, fp);
 
 		if (r == 0)
 			return (-1);
 		return (r);
 	}
 }
 
 static __inline int
 convert_wchar(FILE *fp, wchar_t *wcp, int width, locale_t locale)
 {
 	mbstate_t mbs;
 	int n, nread;
 	wint_t wi;
 
 	mbs = initial_mbs;
 	n = 0;
 	while (width-- != 0 &&
 	    (wi = __fgetwc_mbs(fp, &mbs, &nread, locale)) != WEOF) {
 		if (wcp != SUPPRESS_PTR)
 			*wcp++ = (wchar_t)wi;
 		n += nread;
 	}
 	if (n == 0)
 		return (-1);
 	return (n);
 }
 
 static __inline int
 convert_ccl(FILE *fp, char * p, int width, const char *ccltab)
 {
 	char *p0;
 	int n;
 
 	if (p == SUPPRESS_PTR) {
 		n = 0;
 		while (ccltab[*fp->_p]) {
 			n++, fp->_r--, fp->_p++;
 			if (--width == 0)
 				break;
 			if (fp->_r <= 0 && __srefill(fp)) {
 				if (n == 0)
 					return (-1);
 				break;
 			}
 		}
 	} else {
 		p0 = p;
 		while (ccltab[*fp->_p]) {
 			fp->_r--;
 			*p++ = *fp->_p++;
 			if (--width == 0)
 				break;
 			if (fp->_r <= 0 && __srefill(fp)) {
 				if (p == p0)
 					return (-1);
 				break;
 			}
 		}
 		n = p - p0;
 		if (n == 0)
 			return (0);
 		*p = 0;
 	}
 	return (n);
 }
 
 static __inline int
 convert_wccl(FILE *fp, wchar_t *wcp, int width, const char *ccltab,
     locale_t locale)
 {
 	mbstate_t mbs;
 	wint_t wi;
 	int n, nread;
 
 	mbs = initial_mbs;
 	n = 0;
 	if (wcp == SUPPRESS_PTR) {
 		while ((wi = __fgetwc_mbs(fp, &mbs, &nread, locale)) != WEOF &&
 		    width-- != 0 && ccltab[wctob(wi)])
 			n += nread;
 		if (wi != WEOF)
 			__ungetwc(wi, fp, __get_locale());
 	} else {
 		while ((wi = __fgetwc_mbs(fp, &mbs, &nread, locale)) != WEOF &&
 		    width-- != 0 && ccltab[wctob(wi)]) {
 			*wcp++ = (wchar_t)wi;
 			n += nread;
 		}
 		if (wi != WEOF)
 			__ungetwc(wi, fp, __get_locale());
 		if (n == 0)
 			return (0);
 		*wcp = 0;
 	}
 	return (n);
 }
 
 static __inline int
 convert_string(FILE *fp, char * p, int width)
 {
 	char *p0;
 	int n;
 
 	if (p == SUPPRESS_PTR) {
 		n = 0;
 		while (!isspace(*fp->_p)) {
 			n++, fp->_r--, fp->_p++;
 			if (--width == 0)
 				break;
 			if (fp->_r <= 0 && __srefill(fp))
 				break;
 		}
 	} else {
 		p0 = p;
 		while (!isspace(*fp->_p)) {
 			fp->_r--;
 			*p++ = *fp->_p++;
 			if (--width == 0)
 				break;
 			if (fp->_r <= 0 && __srefill(fp))
 				break;
 		}
 		*p = 0;
 		n = p - p0;
 	}
 	return (n);
 }
 
 static __inline int
 convert_wstring(FILE *fp, wchar_t *wcp, int width, locale_t locale)
 {
 	mbstate_t mbs;
 	wint_t wi;
 	int n, nread;
 
 	mbs = initial_mbs;
 	n = 0;
 	if (wcp == SUPPRESS_PTR) {
 		while ((wi = __fgetwc_mbs(fp, &mbs, &nread, locale)) != WEOF &&
 		    width-- != 0 && !iswspace(wi))
 			n += nread;
 		if (wi != WEOF)
 			__ungetwc(wi, fp, __get_locale());
 	} else {
 		while ((wi = __fgetwc_mbs(fp, &mbs, &nread, locale)) != WEOF &&
 		    width-- != 0 && !iswspace(wi)) {
 			*wcp++ = (wchar_t)wi;
 			n += nread;
 		}
 		if (wi != WEOF)
 			__ungetwc(wi, fp, __get_locale());
 		*wcp = '\0';
 	}
 	return (n);
 }
 
 /*
  * Read an integer, storing it in buf.  The only relevant bit in the
  * flags argument is PFXOK.
  *
  * Return 0 on a match failure, and the number of characters read
  * otherwise.
  */
 static __inline int
 parseint(FILE *fp, char * __restrict buf, int width, int base, int flags)
 {
 	/* `basefix' is used to avoid `if' tests */
 	static const short basefix[17] =
 		{ 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
 	char *p;
 	int c;
 
 	flags |= SIGNOK | NDIGITS | NZDIGITS;
 	for (p = buf; width; width--) {
 		c = *fp->_p;
 		/*
 		 * Switch on the character; `goto ok' if we accept it
 		 * as a part of number.
 		 */
 		switch (c) {
 
 		/*
 		 * The digit 0 is always legal, but is special.  For
 		 * %i conversions, if no digits (zero or nonzero) have
 		 * been scanned (only signs), we will have base==0.
 		 * In that case, we should set it to 8 and enable 0x
 		 * prefixing.  Also, if we have not scanned zero
 		 * digits before this, do not turn off prefixing
 		 * (someone else will turn it off if we have scanned
 		 * any nonzero digits).
 		 */
 		case '0':
 			if (base == 0) {
 				base = 8;
 				flags |= PFXOK;
 			}
 			if (flags & NZDIGITS)
 				flags &= ~(SIGNOK|NZDIGITS|NDIGITS);
 			else
 				flags &= ~(SIGNOK|PFXOK|NDIGITS);
 			goto ok;
 
 		/* 1 through 7 always legal */
 		case '1': case '2': case '3':
 		case '4': case '5': case '6': case '7':
 			base = basefix[base];
 			flags &= ~(SIGNOK | PFXOK | NDIGITS);
 			goto ok;
 
 		/* digits 8 and 9 ok iff decimal or hex */
 		case '8': case '9':
 			base = basefix[base];
 			if (base <= 8)
 				break;	/* not legal here */
 			flags &= ~(SIGNOK | PFXOK | NDIGITS);
 			goto ok;
 
 		/* letters ok iff hex */
 		case 'A': case 'B': case 'C':
 		case 'D': case 'E': case 'F':
 		case 'a': case 'b': case 'c':
 		case 'd': case 'e': case 'f':
 			/* no need to fix base here */
 			if (base <= 10)
 				break;	/* not legal here */
 			flags &= ~(SIGNOK | PFXOK | NDIGITS);
 			goto ok;
 
 		/* sign ok only as first character */
 		case '+': case '-':
 			if (flags & SIGNOK) {
 				flags &= ~SIGNOK;
 				flags |= HAVESIGN;
 				goto ok;
 			}
 			break;
 
 		/*
 		 * x ok iff flag still set & 2nd char (or 3rd char if
 		 * we have a sign).
 		 */
 		case 'x': case 'X':
 			if (flags & PFXOK && p ==
 			    buf + 1 + !!(flags & HAVESIGN)) {
 				base = 16;	/* if %i */
 				flags &= ~PFXOK;
 				goto ok;
 			}
 			break;
 		}
 
 		/*
 		 * If we got here, c is not a legal character for a
 		 * number.  Stop accumulating digits.
 		 */
 		break;
 	ok:
 		/*
 		 * c is legal: store it and look at the next.
 		 */
 		*p++ = c;
 		if (--fp->_r > 0)
 			fp->_p++;
 		else if (__srefill(fp))
 			break;		/* EOF */
 	}
 	/*
 	 * If we had only a sign, it is no good; push back the sign.
 	 * If the number ends in `x', it was [sign] '0' 'x', so push
 	 * back the x and treat it as [sign] '0'.
 	 */
 	if (flags & NDIGITS) {
 		if (p > buf)
 			(void) __ungetc(*(u_char *)--p, fp);
 		return (0);
 	}
 	c = ((u_char *)p)[-1];
 	if (c == 'x' || c == 'X') {
 		--p;
 		(void) __ungetc(c, fp);
 	}
 	return (p - buf);
 }
 
 /*
  * __vfscanf - MT-safe version
  */
 int
 __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
 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);
 }
 
 /*
  * __svfscanf - non-MT-safe version of __vfscanf
  */
 int
 __svfscanf(FILE *fp, locale_t locale, const char *fmt0, va_list ap)
 {
 #define	GETARG(type)	((flags & SUPPRESS) ? SUPPRESS_PTR : va_arg(ap, type))
 	const u_char *fmt = (const u_char *)fmt0;
 	int c;			/* character from format, or conversion */
 	size_t width;		/* field width, or 0 */
 	int flags;		/* flags as defined above */
 	int nassigned;		/* number of fields assigned */
 	int nconversions;	/* number of conversions */
 	int nr;			/* characters read by the current conversion */
 	int nread;		/* number of characters consumed from fp */
 	int base;		/* base argument to conversion function */
 	char ccltab[256];	/* character class table for %[...] */
 	char buf[BUF];		/* buffer for numeric conversions */
 
 	ORIENT(fp, -1);
 
 	nassigned = 0;
 	nconversions = 0;
 	nread = 0;
 	for (;;) {
 		c = *fmt++;
 		if (c == 0)
 			return (nassigned);
 		if (isspace(c)) {
 			while ((fp->_r > 0 || __srefill(fp) == 0) && isspace(*fp->_p))
 				nread++, fp->_r--, fp->_p++;
 			continue;
 		}
 		if (c != '%')
 			goto literal;
 		width = 0;
 		flags = 0;
 		/*
 		 * switch on the format.  continue if done;
 		 * break once format type is derived.
 		 */
 again:		c = *fmt++;
 		switch (c) {
 		case '%':
 literal:
 			if (fp->_r <= 0 && __srefill(fp))
 				goto input_failure;
 			if (*fp->_p != c)
 				goto match_failure;
 			fp->_r--, fp->_p++;
 			nread++;
 			continue;
 
 		case '*':
 			flags |= SUPPRESS;
 			goto again;
 		case 'j':
 			flags |= INTMAXT;
 			goto again;
 		case 'l':
 			if (flags & LONG) {
 				flags &= ~LONG;
 				flags |= LONGLONG;
 			} else
 				flags |= LONG;
 			goto again;
 		case 'q':
 			flags |= LONGLONG;	/* not quite */
 			goto again;
 		case 't':
 			flags |= PTRDIFFT;
 			goto again;
 		case 'z':
 			flags |= SIZET;
 			goto again;
 		case 'L':
 			flags |= LONGDBL;
 			goto again;
 		case 'h':
 			if (flags & SHORT) {
 				flags &= ~SHORT;
 				flags |= SHORTSHORT;
 			} else
 				flags |= SHORT;
 			goto again;
 
 		case '0': case '1': case '2': case '3': case '4':
 		case '5': case '6': case '7': case '8': case '9':
 			width = width * 10 + c - '0';
 			goto again;
 
 		/*
 		 * Conversions.
 		 */
 		case 'd':
 			c = CT_INT;
 			base = 10;
 			break;
 
 		case 'i':
 			c = CT_INT;
 			base = 0;
 			break;
 
 		case 'o':
 			c = CT_INT;
 			flags |= UNSIGNED;
 			base = 8;
 			break;
 
 		case 'u':
 			c = CT_INT;
 			flags |= UNSIGNED;
 			base = 10;
 			break;
 
 		case 'X':
 		case 'x':
 			flags |= PFXOK;	/* enable 0x prefixing */
 			c = CT_INT;
 			flags |= UNSIGNED;
 			base = 16;
 			break;
 
 #ifndef NO_FLOATING_POINT
 		case 'A': case 'E': case 'F': case 'G':
 		case 'a': case 'e': case 'f': case 'g':
 			c = CT_FLOAT;
 			break;
 #endif
 
 		case 'S':
 			flags |= LONG;
 			/* FALLTHROUGH */
 		case 's':
 			c = CT_STRING;
 			break;
 
 		case '[':
 			fmt = __sccl(ccltab, fmt);
 			flags |= NOSKIP;
 			c = CT_CCL;
 			break;
 
 		case 'C':
 			flags |= LONG;
 			/* FALLTHROUGH */
 		case 'c':
 			flags |= NOSKIP;
 			c = CT_CHAR;
 			break;
 
 		case 'p':	/* pointer format is like hex */
 			flags |= POINTER | PFXOK;
 			c = CT_INT;		/* assumes sizeof(uintmax_t) */
 			flags |= UNSIGNED;	/*      >= sizeof(uintptr_t) */
 			base = 16;
 			break;
 
 		case 'n':
 			if (flags & SUPPRESS)	/* ??? */
 				continue;
 			if (flags & SHORTSHORT)
 				*va_arg(ap, char *) = nread;
 			else if (flags & SHORT)
 				*va_arg(ap, short *) = nread;
 			else if (flags & LONG)
 				*va_arg(ap, long *) = nread;
 			else if (flags & LONGLONG)
 				*va_arg(ap, long long *) = nread;
 			else if (flags & INTMAXT)
 				*va_arg(ap, intmax_t *) = nread;
 			else if (flags & SIZET)
 				*va_arg(ap, size_t *) = nread;
 			else if (flags & PTRDIFFT)
 				*va_arg(ap, ptrdiff_t *) = nread;
 			else
 				*va_arg(ap, int *) = nread;
 			continue;
 
 		default:
 			goto match_failure;
 
 		/*
 		 * Disgusting backwards compatibility hack.	XXX
 		 */
 		case '\0':	/* compat */
 			return (EOF);
 		}
 
 		/*
 		 * We have a conversion that requires input.
 		 */
 		if (fp->_r <= 0 && __srefill(fp))
 			goto input_failure;
 
 		/*
 		 * Consume leading white space, except for formats
 		 * that suppress this.
 		 */
 		if ((flags & NOSKIP) == 0) {
 			while (isspace(*fp->_p)) {
 				nread++;
 				if (--fp->_r > 0)
 					fp->_p++;
 				else if (__srefill(fp))
 					goto input_failure;
 			}
 			/*
 			 * Note that there is at least one character in
 			 * the buffer, so conversions that do not set NOSKIP
 			 * ca no longer result in an input failure.
 			 */
 		}
 
 		/*
 		 * Do the conversion.
 		 */
 		switch (c) {
 
 		case CT_CHAR:
 			/* scan arbitrary characters (sets NOSKIP) */
 			if (width == 0)
 				width = 1;
 			if (flags & LONG) {
 				nr = convert_wchar(fp, GETARG(wchar_t *),
 				    width, locale);
 			} else {
 				nr = convert_char(fp, GETARG(char *), width);
 			}
 			if (nr < 0)
 				goto input_failure;
 			break;
 
 		case CT_CCL:
 			/* scan a (nonempty) character class (sets NOSKIP) */
 			if (width == 0)
 				width = (size_t)~0;	/* `infinity' */
 			if (flags & LONG) {
 				nr = convert_wccl(fp, GETARG(wchar_t *), width,
 				    ccltab, locale);
 			} else {
 				nr = convert_ccl(fp, GETARG(char *), width,
 				    ccltab);
 			}
 			if (nr <= 0) {
 				if (nr < 0)
 					goto input_failure;
 				else /* nr == 0 */
 					goto match_failure;
 			}
 			break;
 
 		case CT_STRING:
 			/* like CCL, but zero-length string OK, & no NOSKIP */
 			if (width == 0)
 				width = (size_t)~0;
 			if (flags & LONG) {
 				nr = convert_wstring(fp, GETARG(wchar_t *),
 				    width, locale);
 			} else {
 				nr = convert_string(fp, GETARG(char *), width);
 			}
 			if (nr < 0)
 				goto input_failure;
 			break;
 
 		case CT_INT:
 			/* scan an integer as if by the conversion function */
 #ifdef hardway
 			if (width == 0 || width > sizeof(buf) - 1)
 				width = sizeof(buf) - 1;
 #else
 			/* size_t is unsigned, hence this optimisation */
 			if (--width > sizeof(buf) - 2)
 				width = sizeof(buf) - 2;
 			width++;
 #endif
 			nr = parseint(fp, buf, width, base, flags);
 			if (nr == 0)
 				goto match_failure;
 			if ((flags & SUPPRESS) == 0) {
 				uintmax_t res;
 
 				buf[nr] = '\0';
 				if ((flags & UNSIGNED) == 0)
 				    res = strtoimax_l(buf, (char **)NULL, base, locale);
 				else
 				    res = strtoumax_l(buf, (char **)NULL, base, locale);
 				if (flags & POINTER)
 					*va_arg(ap, void **) =
 							(void *)(uintptr_t)res;
 				else if (flags & SHORTSHORT)
 					*va_arg(ap, char *) = res;
 				else if (flags & SHORT)
 					*va_arg(ap, short *) = res;
 				else if (flags & LONG)
 					*va_arg(ap, long *) = res;
 				else if (flags & LONGLONG)
 					*va_arg(ap, long long *) = res;
 				else if (flags & INTMAXT)
 					*va_arg(ap, intmax_t *) = res;
 				else if (flags & PTRDIFFT)
 					*va_arg(ap, ptrdiff_t *) = res;
 				else if (flags & SIZET)
 					*va_arg(ap, size_t *) = res;
 				else
 					*va_arg(ap, int *) = res;
 			}
 			break;
 
 #ifndef NO_FLOATING_POINT
 		case CT_FLOAT:
 			/* scan a floating point number as if by strtod */
 			if (width == 0 || width > sizeof(buf) - 1)
 				width = sizeof(buf) - 1;
 			nr = parsefloat(fp, buf, buf + width, locale);
 			if (nr == 0)
 				goto match_failure;
 			if ((flags & SUPPRESS) == 0) {
 				if (flags & LONGDBL) {
 					long double res = strtold_l(buf, NULL,
 					    locale);
 					*va_arg(ap, long double *) = res;
 				} else if (flags & LONG) {
 					double res = strtod_l(buf, NULL,
 					    locale);
 					*va_arg(ap, double *) = res;
 				} else {
 					float res = strtof_l(buf, NULL, locale);
 					*va_arg(ap, float *) = res;
 				}
 			}
 			break;
 #endif /* !NO_FLOATING_POINT */
 		}
 		if (!(flags & SUPPRESS))
 			nassigned++;
 		nread += nr;
 		nconversions++;
 	}
 input_failure:
 	return (nconversions != 0 ? nassigned : EOF);
 match_failure:
 	return (nassigned);
 }
 
 /*
  * Fill in the given table from the scanset at the given format
  * (just after `[').  Return a pointer to the character past the
  * closing `]'.  The table has a 1 wherever characters should be
  * considered part of the scanset.
  */
 static const u_char *
 __sccl(char *tab, const u_char *fmt)
 {
 	int c, n, v, i;
 	struct xlocale_collate *table =
 		(struct xlocale_collate*)__get_locale()->components[XLC_COLLATE];
 
 	/* first `clear' the whole table */
 	c = *fmt++;		/* first char hat => negated scanset */
 	if (c == '^') {
 		v = 1;		/* default => accept */
 		c = *fmt++;	/* get new first char */
 	} else
 		v = 0;		/* default => reject */
 
 	/* XXX: Will not work if sizeof(tab*) > sizeof(char) */
 	(void) memset(tab, v, 256);
 
 	if (c == 0)
 		return (fmt - 1);/* format ended before closing ] */
 
 	/*
 	 * Now set the entries corresponding to the actual scanset
 	 * to the opposite of the above.
 	 *
 	 * The first character may be ']' (or '-') without being special;
 	 * the last character may be '-'.
 	 */
 	v = 1 - v;
 	for (;;) {
 		tab[c] = v;		/* take character c */
 doswitch:
 		n = *fmt++;		/* and examine the next */
 		switch (n) {
 
 		case 0:			/* format ended too soon */
 			return (fmt - 1);
 
 		case '-':
 			/*
 			 * A scanset of the form
 			 *	[01+-]
 			 * is defined as `the digit 0, the digit 1,
 			 * the character +, the character -', but
 			 * the effect of a scanset such as
 			 *	[a-zA-Z0-9]
 			 * is implementation defined.  The V7 Unix
 			 * scanf treats `a-z' as `the letters a through
 			 * z', but treats `a-a' as `the letter a, the
 			 * character -, and the letter a'.
 			 *
 			 * For compatibility, the `-' is not considered
 			 * to define a range if the character following
 			 * it is either a close bracket (required by ANSI)
 			 * or is not numerically greater than the character
 			 * we just stored in the table (c).
 			 */
 			n = *fmt;
 			if (n == ']'
 			    || (table->__collate_load_error ? n < c :
 				__collate_range_cmp(n, c) < 0
 			       )
 			   ) {
 				c = '-';
 				break;	/* resume the for(;;) */
 			}
 			fmt++;
 			/* fill in the range */
 			if (table->__collate_load_error) {
 				do {
 					tab[++c] = v;
 				} while (c < n);
 			} else {
 				for (i = 0; i < 256; i ++)
 					if (__collate_range_cmp(c, i) <= 0 &&
 					    __collate_range_cmp(i, n) <= 0
 					   )
 						tab[i] = v;
 			}
 #if 1	/* XXX another disgusting compatibility hack */
 			c = n;
 			/*
 			 * Alas, the V7 Unix scanf also treats formats
 			 * such as [a-c-e] as `the letters a through e'.
 			 * This too is permitted by the standard....
 			 */
 			goto doswitch;
 #else
 			c = *fmt++;
 			if (c == 0)
 				return (fmt - 1);
 			if (c == ']')
 				return (fmt);
 #endif
 			break;
 
 		case ']':		/* end of scanset */
 			return (fmt);
 
 		default:		/* just another character */
 			c = n;
 			break;
 		}
 	}
 	/* NOTREACHED */
 }
 
 #ifndef NO_FLOATING_POINT
 static int
 parsefloat(FILE *fp, char *buf, char *end, locale_t locale)
 {
 	char *commit, *p;
 	int infnanpos = 0, decptpos = 0;
 	enum {
 		S_START, S_GOTSIGN, S_INF, S_NAN, S_DONE, S_MAYBEHEX,
 		S_DIGITS, S_DECPT, S_FRAC, S_EXP, S_EXPDIGITS
 	} state = S_START;
 	unsigned char c;
 	const char *decpt = localeconv_l(locale)->decimal_point;
 	_Bool gotmantdig = 0, ishex = 0;
 
 	/*
 	 * We set commit = p whenever the string we have read so far
 	 * constitutes a valid representation of a floating point
 	 * number by itself.  At some point, the parse will complete
 	 * or fail, and we will ungetc() back to the last commit point.
 	 * To ensure that the file offset gets updated properly, it is
 	 * always necessary to read at least one character that doesn't
 	 * match; thus, we can't short-circuit "infinity" or "nan(...)".
 	 */
 	commit = buf - 1;
 	for (p = buf; p < end; ) {
 		c = *fp->_p;
 reswitch:
 		switch (state) {
 		case S_START:
 			state = S_GOTSIGN;
 			if (c == '-' || c == '+')
 				break;
 			else
 				goto reswitch;
 		case S_GOTSIGN:
 			switch (c) {
 			case '0':
 				state = S_MAYBEHEX;
 				commit = p;
 				break;
 			case 'I':
 			case 'i':
 				state = S_INF;
 				break;
 			case 'N':
 			case 'n':
 				state = S_NAN;
 				break;
 			default:
 				state = S_DIGITS;
 				goto reswitch;
 			}
 			break;
 		case S_INF:
 			if (infnanpos > 6 ||
 			    (c != "nfinity"[infnanpos] &&
 			     c != "NFINITY"[infnanpos]))
 				goto parsedone;
 			if (infnanpos == 1 || infnanpos == 6)
 				commit = p;	/* inf or infinity */
 			infnanpos++;
 			break;
 		case S_NAN:
 			switch (infnanpos) {
 			case 0:
 				if (c != 'A' && c != 'a')
 					goto parsedone;
 				break;
 			case 1:
 				if (c != 'N' && c != 'n')
 					goto parsedone;
 				else
 					commit = p;
 				break;
 			case 2:
 				if (c != '(')
 					goto parsedone;
 				break;
 			default:
 				if (c == ')') {
 					commit = p;
 					state = S_DONE;
 				} else if (!isalnum(c) && c != '_')
 					goto parsedone;
 				break;
 			}
 			infnanpos++;
 			break;
 		case S_DONE:
 			goto parsedone;
 		case S_MAYBEHEX:
 			state = S_DIGITS;
 			if (c == 'X' || c == 'x') {
 				ishex = 1;
 				break;
 			} else {	/* we saw a '0', but no 'x' */
 				gotmantdig = 1;
 				goto reswitch;
 			}
 		case S_DIGITS:
 			if ((ishex && isxdigit(c)) || isdigit(c)) {
 				gotmantdig = 1;
 				commit = p;
 				break;
 			} else {
 				state = S_DECPT;
 				goto reswitch;
 			}
 		case S_DECPT:
 			if (c == decpt[decptpos]) {
 				if (decpt[++decptpos] == '\0') {
 					/* We read the complete decpt seq. */
 					state = S_FRAC;
 					if (gotmantdig)
 						commit = p;
 				}
 				break;
 			} else if (!decptpos) {
 				/* We didn't read any decpt characters. */
 				state = S_FRAC;
 				goto reswitch;
 			} else {
 				/*
 				 * We read part of a multibyte decimal point,
 				 * but the rest is invalid, so bail.
 				 */
 				goto parsedone;
 			}
 		case S_FRAC:
 			if (((c == 'E' || c == 'e') && !ishex) ||
 			    ((c == 'P' || c == 'p') && ishex)) {
 				if (!gotmantdig)
 					goto parsedone;
 				else
 					state = S_EXP;
 			} else if ((ishex && isxdigit(c)) || isdigit(c)) {
 				commit = p;
 				gotmantdig = 1;
 			} else
 				goto parsedone;
 			break;
 		case S_EXP:
 			state = S_EXPDIGITS;
 			if (c == '-' || c == '+')
 				break;
 			else
 				goto reswitch;
 		case S_EXPDIGITS:
 			if (isdigit(c))
 				commit = p;
 			else
 				goto parsedone;
 			break;
 		default:
 			abort();
 		}
 		*p++ = c;
 		if (--fp->_r > 0)
 			fp->_p++;
 		else if (__srefill(fp))
 			break;	/* EOF */
 	}
 
 parsedone:
 	while (commit < --p)
 		__ungetc(*(u_char *)p, fp);
 	*++commit = '\0';
 	return (commit - buf);
 }
 #endif
Index: head/lib/libc/stdio/vfwprintf.c
===================================================================
--- head/lib/libc/stdio/vfwprintf.c	(revision 320471)
+++ head/lib/libc/stdio/vfwprintf.c	(revision 320472)
@@ -1,1109 +1,1109 @@
 /*-
  * Copyright (c) 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
  *
  * This code is derived from software contributed to Berkeley by
  * Chris Torek.
  *
  * Copyright (c) 2011 The FreeBSD Foundation
  * All rights reserved.
  * Portions of this software were developed by David Chisnall
  * under sponsorship from the FreeBSD Foundation.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
 
 #if 0
 #if defined(LIBC_SCCS) && !defined(lint)
 static char sccsid[] = "@(#)vfprintf.c	8.1 (Berkeley) 6/4/93";
 #endif /* LIBC_SCCS and not lint */
 #endif
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
 /*
  * Actual wprintf innards.
  *
  * Avoid making gratuitous changes to this source file; it should be kept
  * as close as possible to vfprintf.c for ease of maintenance.
  */
 
 #include "namespace.h"
 #include <sys/types.h>
 
 #include <ctype.h>
 #include <errno.h>
 #include <limits.h>
 #include <locale.h>
 #include <stdarg.h>
 #include <stddef.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <wchar.h>
 #include <wctype.h>
 #include "un-namespace.h"
 
 #include "libc_private.h"
 #include "local.h"
 #include "fvwrite.h"
 #include "printflocal.h"
 #include "xlocale_private.h"
 
 static int	__sprint(FILE *, struct __suio *, locale_t);
 static int	__sbprintf(FILE *, locale_t, const wchar_t *, va_list) __noinline;
 static wint_t	__xfputwc(wchar_t, FILE *, locale_t);
 static wchar_t	*__mbsconv(char *, int);
 
 #define	CHAR	wchar_t
 #include "printfcommon.h"
 
 struct grouping_state {
 	wchar_t thousands_sep;	/* locale-specific thousands separator */
 	const char *grouping;	/* locale-specific numeric grouping rules */
 	int lead;		/* sig figs before decimal or group sep */
 	int nseps;		/* number of group separators with ' */
 	int nrepeats;		/* number of repeats of the last group */
 };
 
 static const mbstate_t initial_mbs;
 
 static inline wchar_t
 get_decpt(locale_t locale)
 {
 	mbstate_t mbs;
 	wchar_t decpt;
 	int nconv;
 
 	mbs = initial_mbs;
 	nconv = mbrtowc(&decpt, localeconv_l(locale)->decimal_point, MB_CUR_MAX, &mbs);
 	if (nconv == (size_t)-1 || nconv == (size_t)-2)
 		decpt = '.';    /* failsafe */
 	return (decpt);
 }
 
 static inline wchar_t
 get_thousep(locale_t locale)
 {
 	mbstate_t mbs;
 	wchar_t thousep;
 	int nconv;
 
 	mbs = initial_mbs;
 	nconv = mbrtowc(&thousep, localeconv_l(locale)->thousands_sep,
 	    MB_CUR_MAX, &mbs);
 	if (nconv == (size_t)-1 || nconv == (size_t)-2)
 		thousep = '\0';    /* failsafe */
 	return (thousep);
 }
 
 /*
  * Initialize the thousands' grouping state in preparation to print a
  * number with ndigits digits. This routine returns the total number
  * of wide characters that will be printed.
  */
 static int
 grouping_init(struct grouping_state *gs, int ndigits, locale_t locale)
 {
 
 	gs->grouping = localeconv_l(locale)->grouping;
 	gs->thousands_sep = get_thousep(locale);
 
 	gs->nseps = gs->nrepeats = 0;
 	gs->lead = ndigits;
 	while (*gs->grouping != CHAR_MAX) {
 		if (gs->lead <= *gs->grouping)
 			break;
 		gs->lead -= *gs->grouping;
 		if (*(gs->grouping+1)) {
 			gs->nseps++;
 			gs->grouping++;
 		} else
 			gs->nrepeats++;
 	}
 	return (gs->nseps + gs->nrepeats);
 }
 
 /*
  * Print a number with thousands' separators.
  */
 static int
 grouping_print(struct grouping_state *gs, struct io_state *iop,
 	       const CHAR *cp, const CHAR *ep, locale_t locale)
 {
 	const CHAR *cp0 = cp;
 
 	if (io_printandpad(iop, cp, ep, gs->lead, zeroes, locale))
 		return (-1);
 	cp += gs->lead;
 	while (gs->nseps > 0 || gs->nrepeats > 0) {
 		if (gs->nrepeats > 0)
 			gs->nrepeats--;
 		else {
 			gs->grouping--;
 			gs->nseps--;
 		}
 		if (io_print(iop, &gs->thousands_sep, 1, locale))
 			return (-1);
 		if (io_printandpad(iop, cp, ep, *gs->grouping, zeroes, locale))
 			return (-1);
 		cp += *gs->grouping;
 	}
 	if (cp > ep)
 		cp = ep;
 	return (cp - cp0);
 }
 
 
 /*
  * Flush out all the vectors defined by the given uio,
  * then reset it so that it can be reused.
  *
  * XXX The fact that we do this a character at a time and convert to a
  * multibyte character sequence even if the destination is a wide
  * string eclipses the benefits of buffering.
  */
 static int
 __sprint(FILE *fp, struct __suio *uio, locale_t locale)
 {
 	struct __siov *iov;
 	wchar_t *p;
 	int i, len;
 
 	iov = uio->uio_iov;
 	for (; uio->uio_resid != 0; uio->uio_resid -= len, iov++) {
 		p = (wchar_t *)iov->iov_base;
 		len = iov->iov_len;
 		for (i = 0; i < len; i++) {
 			if (__xfputwc(p[i], fp, locale) == WEOF)
 				return (-1);
 		}
 	}
 	uio->uio_iovcnt = 0;
 	return (0);
 }
 
 /*
  * Helper function for `fprintf to unbuffered unix file': creates a
  * temporary buffer.  We only work on write-only files; this avoids
  * worries about ungetc buffers and so forth.
  */
 static int
 __sbprintf(FILE *fp, locale_t locale, const wchar_t *fmt, va_list ap)
 {
 	int ret;
 	FILE fake;
 	unsigned char buf[BUFSIZ];
 
 	/* XXX This is probably not needed. */
 	if (prepwrite(fp) != 0)
 		return (EOF);
 
 	/* copy the important variables */
 	fake._flags = fp->_flags & ~__SNBF;
 	fake._file = fp->_file;
 	fake._cookie = fp->_cookie;
 	fake._write = fp->_write;
 	fake._orientation = fp->_orientation;
 	fake._mbstate = fp->_mbstate;
 
 	/* set up the buffer */
 	fake._bf._base = fake._p = buf;
 	fake._bf._size = fake._w = sizeof(buf);
 	fake._lbfsize = 0;	/* not actually used, but Just In Case */
 
 	/* do the work, then copy any error status */
 	ret = __vfwprintf(&fake, locale, fmt, ap);
 	if (ret >= 0 && __fflush(&fake))
 		ret = WEOF;
 	if (fake._flags & __SERR)
 		fp->_flags |= __SERR;
 	return (ret);
 }
 
 /*
  * Like __fputwc, but handles fake string (__SSTR) files properly.
  * File must already be locked.
  */
 static wint_t
 __xfputwc(wchar_t wc, FILE *fp, locale_t locale)
 {
 	mbstate_t mbs;
 	char buf[MB_LEN_MAX];
 	struct __suio uio;
 	struct __siov iov;
 	size_t len;
 
 	if ((fp->_flags & __SSTR) == 0)
 		return (__fputwc(wc, fp, locale));
 
 	mbs = initial_mbs;
 	if ((len = wcrtomb(buf, wc, &mbs)) == (size_t)-1) {
 		fp->_flags |= __SERR;
 		return (WEOF);
 	}
 	uio.uio_iov = &iov;
 	uio.uio_resid = len;
 	uio.uio_iovcnt = 1;
 	iov.iov_base = buf;
 	iov.iov_len = len;
 	return (__sfvwrite(fp, &uio) != EOF ? (wint_t)wc : WEOF);
 }
 
 /*
  * Convert a multibyte character string argument for the %s format to a wide
  * string representation. ``prec'' specifies the maximum number of bytes
  * to output. If ``prec'' is greater than or equal to zero, we can't assume
  * that the multibyte char. string ends in a null character.
  */
 static wchar_t *
 __mbsconv(char *mbsarg, int prec)
 {
 	mbstate_t mbs;
 	wchar_t *convbuf, *wcp;
 	const char *p;
 	size_t insize, nchars, nconv;
 
 	if (mbsarg == NULL)
 		return (NULL);
 
 	/*
 	 * Supplied argument is a multibyte string; convert it to wide
 	 * characters first.
 	 */
 	if (prec >= 0) {
 		/*
 		 * String is not guaranteed to be NUL-terminated. Find the
 		 * number of characters to print.
 		 */
 		p = mbsarg;
 		insize = nchars = nconv = 0;
 		mbs = initial_mbs;
 		while (nchars != (size_t)prec) {
 			nconv = mbrlen(p, MB_CUR_MAX, &mbs);
 			if (nconv == 0 || nconv == (size_t)-1 ||
 			    nconv == (size_t)-2)
 				break;
 			p += nconv;
 			nchars++;
 			insize += nconv;
 		}
 		if (nconv == (size_t)-1 || nconv == (size_t)-2)
 			return (NULL);
 	} else {
 		insize = strlen(mbsarg);
 		nconv = 0;
 	}
 
 	/*
 	 * Allocate buffer for the result and perform the conversion,
 	 * converting at most `size' bytes of the input multibyte string to
 	 * wide characters for printing.
 	 */
 	convbuf = malloc((insize + 1) * sizeof(*convbuf));
 	if (convbuf == NULL)
 		return (NULL);
 	wcp = convbuf;
 	p = mbsarg;
 	mbs = initial_mbs;
 	while (insize != 0) {
 		nconv = mbrtowc(wcp, p, insize, &mbs);
 		if (nconv == 0 || nconv == (size_t)-1 || nconv == (size_t)-2)
 			break;
 		wcp++;
 		p += nconv;
 		insize -= nconv;
 	}
 	if (nconv == (size_t)-1 || nconv == (size_t)-2) {
 		free(convbuf);
 		return (NULL);
 	}
 	*wcp = L'\0';
 
 	return (convbuf);
 }
 
 /*
  * MT-safe version
  */
 int
 vfwprintf_l(FILE * __restrict fp, locale_t locale,
 		const wchar_t * __restrict fmt0, va_list ap)
 
 {
 	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
 vfwprintf(FILE * __restrict fp, const wchar_t * __restrict fmt0, va_list ap)
 {
 	return vfwprintf_l(fp, __get_locale(), fmt0, ap);
 }
 
 /*
  * The size of the buffer we use as scratch space for integer
  * conversions, among other things.  We need enough space to
  * write a uintmax_t in octal (plus one byte).
  */
 #if UINTMAX_MAX <= UINT64_MAX
 #define	BUF	32
 #else
 #error "BUF must be large enough to format a uintmax_t"
 #endif
 
 /*
  * Non-MT-safe version
  */
 int
 __vfwprintf(FILE *fp, locale_t locale, const wchar_t *fmt0, va_list ap)
 {
 	wchar_t *fmt;		/* format string */
 	wchar_t ch;		/* character from fmt */
 	int n, n2;		/* handy integer (short term usage) */
 	wchar_t *cp;		/* handy char pointer (short term usage) */
 	int flags;		/* flags as above */
 	int ret;		/* return value accumulator */
 	int width;		/* width from format (%8d), or 0 */
 	int prec;		/* precision from format; <0 for N/A */
 	wchar_t sign;		/* sign prefix (' ', '+', '-', or \0) */
 	struct grouping_state gs; /* thousands' grouping info */
 #ifndef NO_FLOATING_POINT
 	/*
 	 * We can decompose the printed representation of floating
 	 * point numbers into several parts, some of which may be empty:
 	 *
 	 * [+|-| ] [0x|0X] MMM . NNN [e|E|p|P] [+|-] ZZ
 	 *    A       B     ---C---      D       E   F
 	 *
 	 * A:	'sign' holds this value if present; '\0' otherwise
 	 * B:	ox[1] holds the 'x' or 'X'; '\0' if not hexadecimal
 	 * C:	cp points to the string MMMNNN.  Leading and trailing
 	 *	zeros are not in the string and must be added.
 	 * D:	expchar holds this character; '\0' if no exponent, e.g. %f
 	 * F:	at least two digits for decimal, at least one digit for hex
 	 */
 	wchar_t decimal_point;	/* locale specific decimal point */
 	int signflag;		/* true if float is negative */
 	union {			/* floating point arguments %[aAeEfFgG] */
 		double dbl;
 		long double ldbl;
 	} fparg;
 	int expt;		/* integer value of exponent */
 	char expchar;		/* exponent character: [eEpP\0] */
 	char *dtoaend;		/* pointer to end of converted digits */
 	int expsize;		/* character count for expstr */
 	int ndig;		/* actual number of digits returned by dtoa */
 	wchar_t expstr[MAXEXPDIG+2];	/* buffer for exponent string: e+ZZZ */
 	char *dtoaresult;	/* buffer allocated by dtoa */
 #endif
 	u_long	ulval;		/* integer arguments %[diouxX] */
 	uintmax_t ujval;	/* %j, %ll, %q, %t, %z integers */
 	int base;		/* base for [diouxX] conversion */
 	int dprec;		/* a copy of prec if [diouxX], 0 otherwise */
 	int realsz;		/* field size expanded by dprec, sign, etc */
 	int size;		/* size of converted field or string */
 	int prsize;             /* max size of printed field */
 	const char *xdigs;	/* digits for [xX] conversion */
 	struct io_state io;	/* I/O buffering state */
 	wchar_t buf[BUF];	/* buffer with space for digits of uintmax_t */
 	wchar_t ox[2];		/* space for 0x hex-prefix */
 	union arg *argtable;	/* args, built due to positional arg */
 	union arg statargtable [STATIC_ARG_TBL_SIZE];
 	int nextarg;		/* 1-based argument index */
 	va_list orgap;		/* original argument pointer */
 	wchar_t *convbuf;	/* multibyte to wide conversion result */
 	int savserr;
 
 	static const char xdigs_lower[16] = "0123456789abcdef";
 	static const char xdigs_upper[16] = "0123456789ABCDEF";
 
 	/* BEWARE, these `goto error' on error. */
 #define	PRINT(ptr, len)	do {			\
 	if (io_print(&io, (ptr), (len), locale))	\
 		goto error; \
 } while (0)
 #define	PAD(howmany, with) { \
 	if (io_pad(&io, (howmany), (with), locale)) \
 		goto error; \
 }
 #define	PRINTANDPAD(p, ep, len, with) {	\
 	if (io_printandpad(&io, (p), (ep), (len), (with), locale)) \
 		goto error; \
 }
 #define	FLUSH() { \
 	if (io_flush(&io, locale)) \
 		goto error; \
 }
 
 	/*
 	 * Get the argument indexed by nextarg.   If the argument table is
 	 * built, use it to get the argument.  If its not, get the next
 	 * argument (and arguments must be gotten sequentially).
 	 */
 #define GETARG(type) \
 	((argtable != NULL) ? *((type*)(&argtable[nextarg++])) : \
 	    (nextarg++, va_arg(ap, type)))
 
 	/*
 	 * To extend shorts properly, we need both signed and unsigned
 	 * argument extraction methods.
 	 */
 #define	SARG() \
 	(flags&LONGINT ? GETARG(long) : \
 	    flags&SHORTINT ? (long)(short)GETARG(int) : \
 	    flags&CHARINT ? (long)(signed char)GETARG(int) : \
 	    (long)GETARG(int))
 #define	UARG() \
 	(flags&LONGINT ? GETARG(u_long) : \
 	    flags&SHORTINT ? (u_long)(u_short)GETARG(int) : \
 	    flags&CHARINT ? (u_long)(u_char)GETARG(int) : \
 	    (u_long)GETARG(u_int))
 #define	INTMAX_SIZE	(INTMAXT|SIZET|PTRDIFFT|LLONGINT)
 #define SJARG() \
 	(flags&INTMAXT ? GETARG(intmax_t) : \
 	    flags&SIZET ? (intmax_t)GETARG(ssize_t) : \
 	    flags&PTRDIFFT ? (intmax_t)GETARG(ptrdiff_t) : \
 	    (intmax_t)GETARG(long long))
 #define	UJARG() \
 	(flags&INTMAXT ? GETARG(uintmax_t) : \
 	    flags&SIZET ? (uintmax_t)GETARG(size_t) : \
 	    flags&PTRDIFFT ? (uintmax_t)GETARG(ptrdiff_t) : \
 	    (uintmax_t)GETARG(unsigned long long))
 
 	/*
 	 * Get * arguments, including the form *nn$.  Preserve the nextarg
 	 * that the argument can be gotten once the type is determined.
 	 */
 #define GETASTER(val) \
 	n2 = 0; \
 	cp = fmt; \
 	while (is_digit(*cp)) { \
 		n2 = 10 * n2 + to_digit(*cp); \
 		cp++; \
 	} \
 	if (*cp == '$') { \
 		int hold = nextarg; \
 		if (argtable == NULL) { \
 			argtable = statargtable; \
 			if (__find_warguments (fmt0, orgap, &argtable)) { \
 				ret = EOF; \
 				goto error; \
 			} \
 		} \
 		nextarg = n2; \
 		val = GETARG (int); \
 		nextarg = hold; \
 		fmt = ++cp; \
 	} else { \
 		val = GETARG (int); \
 	}
 
 
 	/* sorry, fwprintf(read_only_file, L"") returns WEOF, not 0 */
 	if (prepwrite(fp) != 0) {
 		errno = EBADF;
 		return (EOF);
 	}
 
 	savserr = fp->_flags & __SERR;
 	fp->_flags &= ~__SERR;
 
 	convbuf = NULL;
 	fmt = (wchar_t *)fmt0;
 	argtable = NULL;
 	nextarg = 1;
 	va_copy(orgap, ap);
 	io_init(&io, fp);
 	ret = 0;
 #ifndef NO_FLOATING_POINT
 	decimal_point = get_decpt(locale);
 #endif
 
 	/*
 	 * Scan the format for conversions (`%' character).
 	 */
 	for (;;) {
 		for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++)
 			/* void */;
 		if ((n = fmt - cp) != 0) {
 			if ((unsigned)ret + n > INT_MAX) {
 				ret = EOF;
 				errno = EOVERFLOW;
 				goto error;
 			}
 			PRINT(cp, n);
 			ret += n;
 		}
 		if (ch == '\0')
 			goto done;
 		fmt++;		/* skip over '%' */
 
 		flags = 0;
 		dprec = 0;
 		width = 0;
 		prec = -1;
 		gs.grouping = NULL;
 		sign = '\0';
 		ox[1] = '\0';
 
 rflag:		ch = *fmt++;
 reswitch:	switch (ch) {
 		case ' ':
 			/*-
 			 * ``If the space and + flags both appear, the space
 			 * flag will be ignored.''
 			 *	-- ANSI X3J11
 			 */
 			if (!sign)
 				sign = ' ';
 			goto rflag;
 		case '#':
 			flags |= ALT;
 			goto rflag;
 		case '*':
 			/*-
 			 * ``A negative field width argument is taken as a
 			 * - flag followed by a positive field width.''
 			 *	-- ANSI X3J11
 			 * They don't exclude field widths read from args.
 			 */
 			GETASTER (width);
 			if (width >= 0)
 				goto rflag;
 			width = -width;
 			/* FALLTHROUGH */
 		case '-':
 			flags |= LADJUST;
 			goto rflag;
 		case '+':
 			sign = '+';
 			goto rflag;
 		case '\'':
 			flags |= GROUPING;
 			goto rflag;
 		case '.':
 			if ((ch = *fmt++) == '*') {
 				GETASTER (prec);
 				goto rflag;
 			}
 			prec = 0;
 			while (is_digit(ch)) {
 				prec = 10 * prec + to_digit(ch);
 				ch = *fmt++;
 			}
 			goto reswitch;
 		case '0':
 			/*-
 			 * ``Note that 0 is taken as a flag, not as the
 			 * beginning of a field width.''
 			 *	-- ANSI X3J11
 			 */
 			flags |= ZEROPAD;
 			goto rflag;
 		case '1': case '2': case '3': case '4':
 		case '5': case '6': case '7': case '8': case '9':
 			n = 0;
 			do {
 				n = 10 * n + to_digit(ch);
 				ch = *fmt++;
 			} while (is_digit(ch));
 			if (ch == '$') {
 				nextarg = n;
 				if (argtable == NULL) {
 					argtable = statargtable;
 					if (__find_warguments (fmt0, orgap,
 							       &argtable)) {
 						ret = EOF;
 						goto error;
 					}
 				}
 				goto rflag;
 			}
 			width = n;
 			goto reswitch;
 #ifndef NO_FLOATING_POINT
 		case 'L':
 			flags |= LONGDBL;
 			goto rflag;
 #endif
 		case 'h':
 			if (flags & SHORTINT) {
 				flags &= ~SHORTINT;
 				flags |= CHARINT;
 			} else
 				flags |= SHORTINT;
 			goto rflag;
 		case 'j':
 			flags |= INTMAXT;
 			goto rflag;
 		case 'l':
 			if (flags & LONGINT) {
 				flags &= ~LONGINT;
 				flags |= LLONGINT;
 			} else
 				flags |= LONGINT;
 			goto rflag;
 		case 'q':
 			flags |= LLONGINT;	/* not necessarily */
 			goto rflag;
 		case 't':
 			flags |= PTRDIFFT;
 			goto rflag;
 		case 'z':
 			flags |= SIZET;
 			goto rflag;
 		case 'C':
 			flags |= LONGINT;
 			/*FALLTHROUGH*/
 		case 'c':
 			if (flags & LONGINT)
 				*(cp = buf) = (wchar_t)GETARG(wint_t);
 			else
 				*(cp = buf) = (wchar_t)btowc(GETARG(int));
 			size = 1;
 			sign = '\0';
 			break;
 		case 'D':
 			flags |= LONGINT;
 			/*FALLTHROUGH*/
 		case 'd':
 		case 'i':
 			if (flags & INTMAX_SIZE) {
 				ujval = SJARG();
 				if ((intmax_t)ujval < 0) {
 					ujval = -ujval;
 					sign = '-';
 				}
 			} else {
 				ulval = SARG();
 				if ((long)ulval < 0) {
 					ulval = -ulval;
 					sign = '-';
 				}
 			}
 			base = 10;
 			goto number;
 #ifndef NO_FLOATING_POINT
 		case 'a':
 		case 'A':
 			if (ch == 'a') {
 				ox[1] = 'x';
 				xdigs = xdigs_lower;
 				expchar = 'p';
 			} else {
 				ox[1] = 'X';
 				xdigs = xdigs_upper;
 				expchar = 'P';
 			}
 			if (prec >= 0)
 				prec++;
 			if (flags & LONGDBL) {
 				fparg.ldbl = GETARG(long double);
 				dtoaresult =
 				    __hldtoa(fparg.ldbl, xdigs, prec,
 				        &expt, &signflag, &dtoaend);
 			} else {
 				fparg.dbl = GETARG(double);
 				dtoaresult =
 				    __hdtoa(fparg.dbl, xdigs, prec,
 				        &expt, &signflag, &dtoaend);
 			}
 			if (prec < 0)
 				prec = dtoaend - dtoaresult;
 			if (expt == INT_MAX)
 				ox[1] = '\0';
 			if (convbuf != NULL)
 				free(convbuf);
 			ndig = dtoaend - dtoaresult;
 			cp = convbuf = __mbsconv(dtoaresult, -1);
 			freedtoa(dtoaresult);
 			goto fp_common;
 		case 'e':
 		case 'E':
 			expchar = ch;
 			if (prec < 0)	/* account for digit before decpt */
 				prec = DEFPREC + 1;
 			else
 				prec++;
 			goto fp_begin;
 		case 'f':
 		case 'F':
 			expchar = '\0';
 			goto fp_begin;
 		case 'g':
 		case 'G':
 			expchar = ch - ('g' - 'e');
 			if (prec == 0)
 				prec = 1;
 fp_begin:
 			if (prec < 0)
 				prec = DEFPREC;
 			if (convbuf != NULL)
 				free(convbuf);
 			if (flags & LONGDBL) {
 				fparg.ldbl = GETARG(long double);
 				dtoaresult =
 				    __ldtoa(&fparg.ldbl, expchar ? 2 : 3, prec,
 				    &expt, &signflag, &dtoaend);
 			} else {
 				fparg.dbl = GETARG(double);
 				dtoaresult =
 				    dtoa(fparg.dbl, expchar ? 2 : 3, prec,
 				    &expt, &signflag, &dtoaend);
 				if (expt == 9999)
 					expt = INT_MAX;
 			}
 			ndig = dtoaend - dtoaresult;
 			cp = convbuf = __mbsconv(dtoaresult, -1);
 			freedtoa(dtoaresult);
 fp_common:
 			if (signflag)
 				sign = '-';
 			if (expt == INT_MAX) {	/* inf or nan */
 				if (*cp == 'N') {
 					cp = (ch >= 'a') ? L"nan" : L"NAN";
 					sign = '\0';
 				} else
 					cp = (ch >= 'a') ? L"inf" : L"INF";
 				size = 3;
 				flags &= ~ZEROPAD;
 				break;
 			}
 			flags |= FPT;
 			if (ch == 'g' || ch == 'G') {
 				if (expt > -4 && expt <= prec) {
 					/* Make %[gG] smell like %[fF] */
 					expchar = '\0';
 					if (flags & ALT)
 						prec -= expt;
 					else
 						prec = ndig - expt;
 					if (prec < 0)
 						prec = 0;
 				} else {
 					/*
 					 * Make %[gG] smell like %[eE], but
 					 * trim trailing zeroes if no # flag.
 					 */
 					if (!(flags & ALT))
 						prec = ndig;
 				}
 			}
 			if (expchar) {
 				expsize = exponent(expstr, expt - 1, expchar);
 				size = expsize + prec;
 				if (prec > 1 || flags & ALT)
 					++size;
 			} else {
 				/* space for digits before decimal point */
 				if (expt > 0)
 					size = expt;
 				else	/* "0" */
 					size = 1;
 				/* space for decimal pt and following digits */
 				if (prec || flags & ALT)
 					size += prec + 1;
 				if ((flags & GROUPING) && expt > 0)
 					size += grouping_init(&gs, expt, locale);
 			}
 			break;
 #endif /* !NO_FLOATING_POINT */
 		case 'n':
 			/*
 			 * Assignment-like behavior is specified if the
 			 * value overflows or is otherwise unrepresentable.
 			 * C99 says to use `signed char' for %hhn conversions.
 			 */
 			if (flags & LLONGINT)
 				*GETARG(long long *) = ret;
 			else if (flags & SIZET)
 				*GETARG(ssize_t *) = (ssize_t)ret;
 			else if (flags & PTRDIFFT)
 				*GETARG(ptrdiff_t *) = ret;
 			else if (flags & INTMAXT)
 				*GETARG(intmax_t *) = ret;
 			else if (flags & LONGINT)
 				*GETARG(long *) = ret;
 			else if (flags & SHORTINT)
 				*GETARG(short *) = ret;
 			else if (flags & CHARINT)
 				*GETARG(signed char *) = ret;
 			else
 				*GETARG(int *) = ret;
 			continue;	/* no output */
 		case 'O':
 			flags |= LONGINT;
 			/*FALLTHROUGH*/
 		case 'o':
 			if (flags & INTMAX_SIZE)
 				ujval = UJARG();
 			else
 				ulval = UARG();
 			base = 8;
 			goto nosign;
 		case 'p':
 			/*-
 			 * ``The argument shall be a pointer to void.  The
 			 * value of the pointer is converted to a sequence
 			 * of printable characters, in an implementation-
 			 * defined manner.''
 			 *	-- ANSI X3J11
 			 */
 			ujval = (uintmax_t)(uintptr_t)GETARG(void *);
 			base = 16;
 			xdigs = xdigs_lower;
 			flags = flags | INTMAXT;
 			ox[1] = 'x';
 			goto nosign;
 		case 'S':
 			flags |= LONGINT;
 			/*FALLTHROUGH*/
 		case 's':
 			if (flags & LONGINT) {
 				if ((cp = GETARG(wchar_t *)) == NULL)
 					cp = L"(null)";
 			} else {
 				char *mbp;
 
 				if (convbuf != NULL)
 					free(convbuf);
 				if ((mbp = GETARG(char *)) == NULL)
 					cp = L"(null)";
 				else {
 					convbuf = __mbsconv(mbp, prec);
 					if (convbuf == NULL) {
 						fp->_flags |= __SERR;
 						goto error;
 					}
 					cp = convbuf;
 				}
 			}
 			size = (prec >= 0) ? wcsnlen(cp, prec) : wcslen(cp);
 			sign = '\0';
 			break;
 		case 'U':
 			flags |= LONGINT;
 			/*FALLTHROUGH*/
 		case 'u':
 			if (flags & INTMAX_SIZE)
 				ujval = UJARG();
 			else
 				ulval = UARG();
 			base = 10;
 			goto nosign;
 		case 'X':
 			xdigs = xdigs_upper;
 			goto hex;
 		case 'x':
 			xdigs = xdigs_lower;
 hex:
 			if (flags & INTMAX_SIZE)
 				ujval = UJARG();
 			else
 				ulval = UARG();
 			base = 16;
 			/* leading 0x/X only if non-zero */
 			if (flags & ALT &&
 			    (flags & INTMAX_SIZE ? ujval != 0 : ulval != 0))
 				ox[1] = ch;
 
 			flags &= ~GROUPING;
 			/* unsigned conversions */
 nosign:			sign = '\0';
 			/*-
 			 * ``... diouXx conversions ... if a precision is
 			 * specified, the 0 flag will be ignored.''
 			 *	-- ANSI X3J11
 			 */
 number:			if ((dprec = prec) >= 0)
 				flags &= ~ZEROPAD;
 
 			/*-
 			 * ``The result of converting a zero value with an
 			 * explicit precision of zero is no characters.''
 			 *	-- ANSI X3J11
 			 *
 			 * ``The C Standard is clear enough as is.  The call
 			 * printf("%#.0o", 0) should print 0.''
 			 *	-- Defect Report #151
 			 */
 			cp = buf + BUF;
 			if (flags & INTMAX_SIZE) {
 				if (ujval != 0 || prec != 0 ||
 				    (flags & ALT && base == 8))
 					cp = __ujtoa(ujval, cp, base,
 					    flags & ALT, xdigs);
 			} else {
 				if (ulval != 0 || prec != 0 ||
 				    (flags & ALT && base == 8))
 					cp = __ultoa(ulval, cp, base,
 					    flags & ALT, xdigs);
 			}
 			size = buf + BUF - cp;
 			if (size > BUF)	/* should never happen */
 				abort();
 			if ((flags & GROUPING) && size != 0)
 				size += grouping_init(&gs, size, locale);
 			break;
 		default:	/* "%?" prints ?, unless ? is NUL */
 			if (ch == '\0')
 				goto done;
 			/* pretend it was %c with argument ch */
 			cp = buf;
 			*cp = ch;
 			size = 1;
 			sign = '\0';
 			break;
 		}
 
 		/*
 		 * All reasonable formats wind up here.  At this point, `cp'
 		 * points to a string which (if not flags&LADJUST) should be
 		 * padded out to `width' places.  If flags&ZEROPAD, it should
 		 * first be prefixed by any sign or other prefix; otherwise,
 		 * it should be blank padded before the prefix is emitted.
 		 * After any left-hand padding and prefixing, emit zeroes
 		 * required by a decimal [diouxX] precision, then print the
 		 * string proper, then emit zeroes required by any leftover
 		 * floating precision; finally, if LADJUST, pad with blanks.
 		 *
 		 * Compute actual size, so we know how much to pad.
 		 * size excludes decimal prec; realsz includes it.
 		 */
 		realsz = dprec > size ? dprec : size;
 		if (sign)
 			realsz++;
 		if (ox[1])
 			realsz += 2;
 
 		prsize = width > realsz ? width : realsz;
 		if ((unsigned)ret + prsize > INT_MAX) {
 			ret = EOF;
 			errno = EOVERFLOW;
 			goto error;
 		}
 
 		/* right-adjusting blank padding */
 		if ((flags & (LADJUST|ZEROPAD)) == 0)
 			PAD(width - realsz, blanks);
 
 		/* prefix */
 		if (sign)
 			PRINT(&sign, 1);
 
 		if (ox[1]) {	/* ox[1] is either x, X, or \0 */
 			ox[0] = '0';
 			PRINT(ox, 2);
 		}
 
 		/* right-adjusting zero padding */
 		if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
 			PAD(width - realsz, zeroes);
 
 		/* the string or number proper */
 #ifndef NO_FLOATING_POINT
 		if ((flags & FPT) == 0) {
 #endif
 			/* leading zeroes from decimal precision */
 			PAD(dprec - size, zeroes);
 			if (gs.grouping) {
 				if (grouping_print(&gs, &io, cp, buf+BUF, locale) < 0)
 					goto error;
 			} else {
 				PRINT(cp, size);
 			}
 #ifndef NO_FLOATING_POINT
 		} else {	/* glue together f_p fragments */
 			if (!expchar) {	/* %[fF] or sufficiently short %[gG] */
 				if (expt <= 0) {
 					PRINT(zeroes, 1);
 					if (prec || flags & ALT)
 						PRINT(&decimal_point, 1);
 					PAD(-expt, zeroes);
 					/* already handled initial 0's */
 					prec += expt;
 				} else {
 					if (gs.grouping) {
 						n = grouping_print(&gs, &io,
 						    cp, convbuf + ndig, locale);
 						if (n < 0)
 							goto error;
 						cp += n;
 					} else {
 						PRINTANDPAD(cp, convbuf + ndig,
 						    expt, zeroes);
 						cp += expt;
 					}
 					if (prec || flags & ALT)
 						PRINT(&decimal_point, 1);
 				}
 				PRINTANDPAD(cp, convbuf + ndig, prec, zeroes);
 			} else {	/* %[eE] or sufficiently long %[gG] */
 				if (prec > 1 || flags & ALT) {
 					buf[0] = *cp++;
 					buf[1] = decimal_point;
 					PRINT(buf, 2);
 					PRINT(cp, ndig-1);
 					PAD(prec - ndig, zeroes);
 				} else	/* XeYYY */
 					PRINT(cp, 1);
 				PRINT(expstr, expsize);
 			}
 		}
 #endif
 		/* left-adjusting padding (always blank) */
 		if (flags & LADJUST)
 			PAD(width - realsz, blanks);
 
 		/* finally, adjust ret */
 		ret += prsize;
 
 		FLUSH();	/* copy out the I/O vectors */
 	}
 done:
 	FLUSH();
 error:
 	va_end(orgap);
 	if (convbuf != NULL)
 		free(convbuf);
 	if (__sferror(fp))
 		ret = EOF;
 	else
 		fp->_flags |= savserr;
 	if ((argtable != NULL) && (argtable != statargtable))
 		free (argtable);
 	return (ret);
 	/* NOTREACHED */
 }
Index: head/lib/libc/stdio/vfwscanf.c
===================================================================
--- head/lib/libc/stdio/vfwscanf.c	(revision 320471)
+++ head/lib/libc/stdio/vfwscanf.c	(revision 320472)
@@ -1,948 +1,948 @@
 /*-
  * Copyright (c) 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
  *
  * This code is derived from software contributed to Berkeley by
  * Chris Torek.
  *
  * Copyright (c) 2011 The FreeBSD Foundation
  * All rights reserved.
  * Portions of this software were developed by David Chisnall
  * under sponsorship from the FreeBSD Foundation.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
 
 #if 0
 #if defined(LIBC_SCCS) && !defined(lint)
 static char sccsid[] = "@(#)vfscanf.c	8.1 (Berkeley) 6/4/93";
 #endif /* LIBC_SCCS and not lint */
 #endif
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
 #include "namespace.h"
 #include <ctype.h>
 #include <inttypes.h>
 #include <limits.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <stddef.h>
 #include <stdarg.h>
 #include <string.h>
 #include <wchar.h>
 #include <wctype.h>
 #include "un-namespace.h"
 
 #include "libc_private.h"
 #include "local.h"
 #include "xlocale_private.h"
 
 #define	BUF		513	/* Maximum length of numeric string. */
 
 /*
  * Flags used during conversion.
  */
 #define	LONG		0x01	/* l: long or double */
 #define	LONGDBL		0x02	/* L: long double */
 #define	SHORT		0x04	/* h: short */
 #define	SUPPRESS	0x08	/* *: suppress assignment */
 #define	POINTER		0x10	/* p: void * (as hex) */
 #define	NOSKIP		0x20	/* [ or c: do not skip blanks */
 #define	LONGLONG	0x400	/* ll: long long (+ deprecated q: quad) */
 #define	INTMAXT		0x800	/* j: intmax_t */
 #define	PTRDIFFT	0x1000	/* t: ptrdiff_t */
 #define	SIZET		0x2000	/* z: size_t */
 #define	SHORTSHORT	0x4000	/* hh: char */
 #define	UNSIGNED	0x8000	/* %[oupxX] conversions */
 
 /*
  * The following are used in integral conversions only:
  * SIGNOK, NDIGITS, PFXOK, and NZDIGITS
  */
 #define	SIGNOK		0x40	/* +/- is (still) legal */
 #define	NDIGITS		0x80	/* no digits detected */
 #define	PFXOK		0x100	/* 0x prefix is (still) legal */
 #define	NZDIGITS	0x200	/* no zero digits detected */
 #define	HAVESIGN	0x10000	/* sign detected */
 
 /*
  * Conversion types.
  */
 #define	CT_CHAR		0	/* %c conversion */
 #define	CT_CCL		1	/* %[...] conversion */
 #define	CT_STRING	2	/* %s conversion */
 #define	CT_INT		3	/* %[dioupxX] conversion */
 #define	CT_FLOAT	4	/* %[efgEFG] conversion */
 
 #ifndef NO_FLOATING_POINT
 static int parsefloat(FILE *, wchar_t *, wchar_t *, locale_t);
 #endif
 
 struct ccl {
 	const wchar_t *start;	/* character class start */
 	const wchar_t *end;	/* character class end */
 	int compl;		/* ccl is complemented? */
 };
 
 static __inline int
 inccl(const struct ccl *ccl, wint_t wi)
 {
 
 	if (ccl->compl) {
 		return (wmemchr(ccl->start, wi, ccl->end - ccl->start)
 		    == NULL);
 	} else {
 		return (wmemchr(ccl->start, wi, ccl->end - ccl->start) != NULL);
 	}
 }
 
 /*
  * Conversion functions are passed a pointer to this object instead of
  * a real parameter to indicate that the assignment-suppression (*)
  * flag was specified.  We could use a NULL pointer to indicate this,
  * but that would mask bugs in applications that call scanf() with a
  * NULL pointer.
  */
 static const int suppress;
 #define	SUPPRESS_PTR	((void *)&suppress)
 
 static const mbstate_t initial_mbs;
 
 /*
  * The following conversion functions return the number of characters consumed,
  * or -1 on input failure.  Character class conversion returns 0 on match
  * failure.
  */
 
 static __inline int
 convert_char(FILE *fp, char * mbp, int width, locale_t locale)
 {
 	mbstate_t mbs;
 	size_t nconv;
 	wint_t wi;
 	int n;
 
 	n = 0;
 	mbs = initial_mbs;
 	while (width-- != 0 && (wi = __fgetwc(fp, locale)) != WEOF) {
 		if (mbp != SUPPRESS_PTR) {
 			nconv = wcrtomb(mbp, wi, &mbs);
 			if (nconv == (size_t)-1)
 				return (-1);
 			mbp += nconv;
 		}
 		n++;
 	}
 	if (n == 0)
 		return (-1);
 	return (n);
 }
 
 static __inline int
 convert_wchar(FILE *fp, wchar_t *wcp, int width, locale_t locale)
 {
 	wint_t wi;
 	int n;
 
 	n = 0;
 	while (width-- != 0 && (wi = __fgetwc(fp, locale)) != WEOF) {
 		if (wcp != SUPPRESS_PTR)
 			*wcp++ = (wchar_t)wi;
 		n++;
 	}
 	if (n == 0)
 		return (-1);
 	return (n);
 }
 
 static __inline int
 convert_ccl(FILE *fp, char * mbp, int width, const struct ccl *ccl,
     locale_t locale)
 {
 	mbstate_t mbs;
 	size_t nconv;
 	wint_t wi;
 	int n;
 
 	n = 0;
 	mbs = initial_mbs;
 	while ((wi = __fgetwc(fp, locale)) != WEOF &&
 	    width-- != 0 && inccl(ccl, wi)) {
 		if (mbp != SUPPRESS_PTR) {
 			nconv = wcrtomb(mbp, wi, &mbs);
 			if (nconv == (size_t)-1)
 				return (-1);
 			mbp += nconv;
 		}
 		n++;
 	}
 	if (wi != WEOF)
 		__ungetwc(wi, fp, locale);
 	if (mbp != SUPPRESS_PTR)
 		*mbp = 0;
 	return (n);
 }
 
 static __inline int
 convert_wccl(FILE *fp, wchar_t *wcp, int width, const struct ccl *ccl,
     locale_t locale)
 {
 	wchar_t *wcp0;
 	wint_t wi;
 	int n;
 
 	if (wcp == SUPPRESS_PTR) {
 		n = 0;
 		while ((wi = __fgetwc(fp, locale)) != WEOF &&
 		    width-- != 0 && inccl(ccl, wi))
 			n++;
 		if (wi != WEOF)
 			__ungetwc(wi, fp, locale);
 	} else {
 		wcp0 = wcp;
 		while ((wi = __fgetwc(fp, locale)) != WEOF &&
 		    width-- != 0 && inccl(ccl, wi))
 			*wcp++ = (wchar_t)wi;
 		if (wi != WEOF)
 			__ungetwc(wi, fp, locale);
 		n = wcp - wcp0;
 		if (n == 0)
 			return (0);
 		*wcp = 0;
 	}
 	return (n);
 }
 
 static __inline int
 convert_string(FILE *fp, char * mbp, int width, locale_t locale)
 {
 	mbstate_t mbs;
 	size_t nconv;
 	wint_t wi;
 	int nread;
 
 	mbs = initial_mbs;
 	nread = 0;
 	while ((wi = __fgetwc(fp, locale)) != WEOF && width-- != 0 &&
 	    !iswspace(wi)) {
 		if (mbp != SUPPRESS_PTR) {
 			nconv = wcrtomb(mbp, wi, &mbs);
 			if (nconv == (size_t)-1)
 				return (-1);
 			mbp += nconv;
 		}
 		nread++;
 	}
 	if (wi != WEOF)
 		__ungetwc(wi, fp, locale);
 	if (mbp != SUPPRESS_PTR)
 		*mbp = 0;
 	return (nread);
 }
 
 static __inline int
 convert_wstring(FILE *fp, wchar_t *wcp, int width, locale_t locale)
 {
 	wchar_t *wcp0;
 	wint_t wi;
 	int nread;
 
 	nread = 0;
 	if (wcp == SUPPRESS_PTR) {
 		while ((wi = __fgetwc(fp, locale)) != WEOF &&
 		    width-- != 0 && !iswspace(wi))
 			nread++;
 		if (wi != WEOF)
 			__ungetwc(wi, fp, locale);
 	} else {
 		wcp0 = wcp;
 		while ((wi = __fgetwc(fp, locale)) != WEOF &&
 		    width-- != 0 && !iswspace(wi)) {
 			*wcp++ = (wchar_t)wi;
 			nread++;
 		}
 		if (wi != WEOF)
 			__ungetwc(wi, fp, locale);
 		*wcp = '\0';
 	}
 	return (nread);
 }
 
 /*
  * Read an integer, storing it in buf.  The only relevant bit in the
  * flags argument is PFXOK.
  *
  * Return 0 on a match failure, and the number of characters read
  * otherwise.
  */
 static __inline int
 parseint(FILE *fp, wchar_t *buf, int width, int base, int flags,
     locale_t locale)
 {
 	/* `basefix' is used to avoid `if' tests */
 	static const short basefix[17] =
 		{ 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
 	wchar_t *wcp;
 	int c;
 
 	flags |= SIGNOK | NDIGITS | NZDIGITS;
 	for (wcp = buf; width; width--) {
 		c = __fgetwc(fp, locale);
 		/*
 		 * Switch on the character; `goto ok' if we accept it
 		 * as a part of number.
 		 */
 		switch (c) {
 
 		/*
 		 * The digit 0 is always legal, but is special.  For
 		 * %i conversions, if no digits (zero or nonzero) have
 		 * been scanned (only signs), we will have base==0.
 		 * In that case, we should set it to 8 and enable 0x
 		 * prefixing.  Also, if we have not scanned zero
 		 * digits before this, do not turn off prefixing
 		 * (someone else will turn it off if we have scanned
 		 * any nonzero digits).
 		 */
 		case '0':
 			if (base == 0) {
 				base = 8;
 				flags |= PFXOK;
 			}
 			if (flags & NZDIGITS)
 				flags &= ~(SIGNOK|NZDIGITS|NDIGITS);
 			else
 				flags &= ~(SIGNOK|PFXOK|NDIGITS);
 			goto ok;
 
 		/* 1 through 7 always legal */
 		case '1': case '2': case '3':
 		case '4': case '5': case '6': case '7':
 			base = basefix[base];
 			flags &= ~(SIGNOK | PFXOK | NDIGITS);
 			goto ok;
 
 		/* digits 8 and 9 ok iff decimal or hex */
 		case '8': case '9':
 			base = basefix[base];
 			if (base <= 8)
 				break;	/* not legal here */
 			flags &= ~(SIGNOK | PFXOK | NDIGITS);
 			goto ok;
 
 		/* letters ok iff hex */
 		case 'A': case 'B': case 'C':
 		case 'D': case 'E': case 'F':
 		case 'a': case 'b': case 'c':
 		case 'd': case 'e': case 'f':
 			/* no need to fix base here */
 			if (base <= 10)
 				break;	/* not legal here */
 			flags &= ~(SIGNOK | PFXOK | NDIGITS);
 			goto ok;
 
 		/* sign ok only as first character */
 		case '+': case '-':
 			if (flags & SIGNOK) {
 				flags &= ~SIGNOK;
 				flags |= HAVESIGN;
 				goto ok;
 			}
 			break;
 
 		/*
 		 * x ok iff flag still set & 2nd char (or 3rd char if
 		 * we have a sign).
 		 */
 		case 'x': case 'X':
 			if (flags & PFXOK && wcp ==
 			    buf + 1 + !!(flags & HAVESIGN)) {
 				base = 16;	/* if %i */
 				flags &= ~PFXOK;
 				goto ok;
 			}
 			break;
 		}
 
 		/*
 		 * If we got here, c is not a legal character for a
 		 * number.  Stop accumulating digits.
 		 */
 		if (c != WEOF)
 			__ungetwc(c, fp, locale);
 		break;
 	ok:
 		/*
 		 * c is legal: store it and look at the next.
 		 */
 		*wcp++ = (wchar_t)c;
 	}
 	/*
 	 * If we had only a sign, it is no good; push back the sign.
 	 * If the number ends in `x', it was [sign] '0' 'x', so push
 	 * back the x and treat it as [sign] '0'.
 	 */
 	if (flags & NDIGITS) {
 		if (wcp > buf)
 			__ungetwc(*--wcp, fp, locale);
 		return (0);
 	}
 	c = wcp[-1];
 	if (c == 'x' || c == 'X') {
 		--wcp;
 		__ungetwc(c, fp, locale);
 	}
 	return (wcp - buf);
 }
 
 /*
  * MT-safe version.
  */
 int
 vfwscanf_l(FILE * __restrict fp, locale_t locale,
 		const wchar_t * __restrict fmt, va_list ap)
 {
 	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
 vfwscanf(FILE * __restrict fp, const wchar_t * __restrict fmt, va_list ap)
 {
 	return vfwscanf_l(fp, __get_locale(), fmt, ap);
 }
 
 /*
  * Non-MT-safe version.
  */
 int
 __vfwscanf(FILE * __restrict fp, locale_t locale,
 		const wchar_t * __restrict fmt, va_list ap)
 {
 #define	GETARG(type)	((flags & SUPPRESS) ? SUPPRESS_PTR : va_arg(ap, type))
 	wint_t c;		/* character from format, or conversion */
 	size_t width;		/* field width, or 0 */
 	int flags;		/* flags as defined above */
 	int nassigned;		/* number of fields assigned */
 	int nconversions;	/* number of conversions */
 	int nr;			/* characters read by the current conversion */
 	int nread;		/* number of characters consumed from fp */
 	int base;		/* base argument to conversion function */
 	struct ccl ccl;		/* character class info */
 	wchar_t buf[BUF];	/* buffer for numeric conversions */
 	wint_t wi;		/* handy wint_t */
 
 	nassigned = 0;
 	nconversions = 0;
 	nread = 0;
 	ccl.start = ccl.end = NULL;
 	for (;;) {
 		c = *fmt++;
 		if (c == 0)
 			return (nassigned);
 		if (iswspace(c)) {
 			while ((c = __fgetwc(fp, locale)) != WEOF &&
 			    iswspace_l(c, locale))
 				nread++;
 			if (c != WEOF)
 				__ungetwc(c, fp, locale);
 			continue;
 		}
 		if (c != '%')
 			goto literal;
 		width = 0;
 		flags = 0;
 		/*
 		 * switch on the format.  continue if done;
 		 * break once format type is derived.
 		 */
 again:		c = *fmt++;
 		switch (c) {
 		case '%':
 literal:
 			if ((wi = __fgetwc(fp, locale)) == WEOF)
 				goto input_failure;
 			if (wi != c) {
 				__ungetwc(wi, fp, locale);
 				goto input_failure;
 			}
 			nread++;
 			continue;
 
 		case '*':
 			flags |= SUPPRESS;
 			goto again;
 		case 'j':
 			flags |= INTMAXT;
 			goto again;
 		case 'l':
 			if (flags & LONG) {
 				flags &= ~LONG;
 				flags |= LONGLONG;
 			} else
 				flags |= LONG;
 			goto again;
 		case 'q':
 			flags |= LONGLONG;	/* not quite */
 			goto again;
 		case 't':
 			flags |= PTRDIFFT;
 			goto again;
 		case 'z':
 			flags |= SIZET;
 			goto again;
 		case 'L':
 			flags |= LONGDBL;
 			goto again;
 		case 'h':
 			if (flags & SHORT) {
 				flags &= ~SHORT;
 				flags |= SHORTSHORT;
 			} else
 				flags |= SHORT;
 			goto again;
 
 		case '0': case '1': case '2': case '3': case '4':
 		case '5': case '6': case '7': case '8': case '9':
 			width = width * 10 + c - '0';
 			goto again;
 
 		/*
 		 * Conversions.
 		 */
 		case 'd':
 			c = CT_INT;
 			base = 10;
 			break;
 
 		case 'i':
 			c = CT_INT;
 			base = 0;
 			break;
 
 		case 'o':
 			c = CT_INT;
 			flags |= UNSIGNED;
 			base = 8;
 			break;
 
 		case 'u':
 			c = CT_INT;
 			flags |= UNSIGNED;
 			base = 10;
 			break;
 
 		case 'X':
 		case 'x':
 			flags |= PFXOK;	/* enable 0x prefixing */
 			c = CT_INT;
 			flags |= UNSIGNED;
 			base = 16;
 			break;
 
 #ifndef NO_FLOATING_POINT
 		case 'A': case 'E': case 'F': case 'G':
 		case 'a': case 'e': case 'f': case 'g':
 			c = CT_FLOAT;
 			break;
 #endif
 
 		case 'S':
 			flags |= LONG;
 			/* FALLTHROUGH */
 		case 's':
 			c = CT_STRING;
 			break;
 
 		case '[':
 			ccl.start = fmt;
 			if (*fmt == '^') {
 				ccl.compl = 1;
 				fmt++;
 			} else
 				ccl.compl = 0;
 			if (*fmt == ']')
 				fmt++;
 			while (*fmt != '\0' && *fmt != ']')
 				fmt++;
 			ccl.end = fmt;
 			fmt++;
 			flags |= NOSKIP;
 			c = CT_CCL;
 			break;
 
 		case 'C':
 			flags |= LONG;
 			/* FALLTHROUGH */
 		case 'c':
 			flags |= NOSKIP;
 			c = CT_CHAR;
 			break;
 
 		case 'p':	/* pointer format is like hex */
 			flags |= POINTER | PFXOK;
 			c = CT_INT;		/* assumes sizeof(uintmax_t) */
 			flags |= UNSIGNED;	/*      >= sizeof(uintptr_t) */
 			base = 16;
 			break;
 
 		case 'n':
 			if (flags & SUPPRESS)	/* ??? */
 				continue;
 			if (flags & SHORTSHORT)
 				*va_arg(ap, char *) = nread;
 			else if (flags & SHORT)
 				*va_arg(ap, short *) = nread;
 			else if (flags & LONG)
 				*va_arg(ap, long *) = nread;
 			else if (flags & LONGLONG)
 				*va_arg(ap, long long *) = nread;
 			else if (flags & INTMAXT)
 				*va_arg(ap, intmax_t *) = nread;
 			else if (flags & SIZET)
 				*va_arg(ap, size_t *) = nread;
 			else if (flags & PTRDIFFT)
 				*va_arg(ap, ptrdiff_t *) = nread;
 			else
 				*va_arg(ap, int *) = nread;
 			continue;
 
 		default:
 			goto match_failure;
 
 		/*
 		 * Disgusting backwards compatibility hack.	XXX
 		 */
 		case '\0':	/* compat */
 			return (EOF);
 		}
 
 		/*
 		 * Consume leading white space, except for formats
 		 * that suppress this.
 		 */
 		if ((flags & NOSKIP) == 0) {
 			while ((wi = __fgetwc(fp, locale)) != WEOF && iswspace(wi))
 				nread++;
 			if (wi == WEOF)
 				goto input_failure;
 			__ungetwc(wi, fp, locale);
 		}
 
 		/*
 		 * Do the conversion.
 		 */
 		switch (c) {
 
 		case CT_CHAR:
 			/* scan arbitrary characters (sets NOSKIP) */
 			if (width == 0)
 				width = 1;
 			if (flags & LONG) {
 				nr = convert_wchar(fp, GETARG(wchar_t *), width,
 				    locale);
 			} else {
 				nr = convert_char(fp, GETARG(char *), width,
 				    locale);
 			}
 			if (nr < 0)
 				goto input_failure;
 			break;
 
 		case CT_CCL:
 			/* scan a (nonempty) character class (sets NOSKIP) */
 			if (width == 0)
 				width = (size_t)~0;	/* `infinity' */
 			/* take only those things in the class */
 			if (flags & LONG) {
 				nr = convert_wccl(fp, GETARG(wchar_t *), width,
 				    &ccl, locale);
 			} else {
 				nr = convert_ccl(fp, GETARG(char *), width,
 				    &ccl, locale);
 			}
 			if (nr <= 0) {
 				if (nr < 0)
 					goto input_failure;
 				else /* nr == 0 */
 					goto match_failure;
 			}
 			break;
 
 		case CT_STRING:
 			/* like CCL, but zero-length string OK, & no NOSKIP */
 			if (width == 0)
 				width = (size_t)~0;
 			if (flags & LONG) {
 				nr = convert_wstring(fp, GETARG(wchar_t *),
 				    width, locale);
 			} else {
 				nr = convert_string(fp, GETARG(char *), width,
 				    locale);
 			}
 			if (nr < 0)
 				goto input_failure;
 			break;
 
 		case CT_INT:
 			/* scan an integer as if by the conversion function */
 			if (width == 0 || width > sizeof(buf) /
 			    sizeof(*buf) - 1)
 				width = sizeof(buf) / sizeof(*buf) - 1;
 
 			nr = parseint(fp, buf, width, base, flags, locale);
 			if (nr == 0)
 				goto match_failure;
 			if ((flags & SUPPRESS) == 0) {
 				uintmax_t res;
 
 				buf[nr] = L'\0';
 				if ((flags & UNSIGNED) == 0)
 				    res = wcstoimax(buf, NULL, base);
 				else
 				    res = wcstoumax(buf, NULL, base);
 				if (flags & POINTER)
 					*va_arg(ap, void **) =
 							(void *)(uintptr_t)res;
 				else if (flags & SHORTSHORT)
 					*va_arg(ap, char *) = res;
 				else if (flags & SHORT)
 					*va_arg(ap, short *) = res;
 				else if (flags & LONG)
 					*va_arg(ap, long *) = res;
 				else if (flags & LONGLONG)
 					*va_arg(ap, long long *) = res;
 				else if (flags & INTMAXT)
 					*va_arg(ap, intmax_t *) = res;
 				else if (flags & PTRDIFFT)
 					*va_arg(ap, ptrdiff_t *) = res;
 				else if (flags & SIZET)
 					*va_arg(ap, size_t *) = res;
 				else
 					*va_arg(ap, int *) = res;
 			}
 			break;
 
 #ifndef NO_FLOATING_POINT
 		case CT_FLOAT:
 			/* scan a floating point number as if by strtod */
 			if (width == 0 || width > sizeof(buf) /
 			    sizeof(*buf) - 1)
 				width = sizeof(buf) / sizeof(*buf) - 1;
 			nr = parsefloat(fp, buf, buf + width, locale);
 			if (nr == 0)
 				goto match_failure;
 			if ((flags & SUPPRESS) == 0) {
 				if (flags & LONGDBL) {
 					long double res = wcstold(buf, NULL);
 					*va_arg(ap, long double *) = res;
 				} else if (flags & LONG) {
 					double res = wcstod(buf, NULL);
 					*va_arg(ap, double *) = res;
 				} else {
 					float res = wcstof(buf, NULL);
 					*va_arg(ap, float *) = res;
 				}
 			}
 			break;
 #endif /* !NO_FLOATING_POINT */
 		}
 		if (!(flags & SUPPRESS))
 			nassigned++;
 		nread += nr;
 		nconversions++;
 	}
 input_failure:
 	return (nconversions != 0 ? nassigned : EOF);
 match_failure:
 	return (nassigned);
 }
 
 #ifndef NO_FLOATING_POINT
 static int
 parsefloat(FILE *fp, wchar_t *buf, wchar_t *end, locale_t locale)
 {
 	mbstate_t mbs;
 	size_t nconv;
 	wchar_t *commit, *p;
 	int infnanpos = 0;
 	enum {
 		S_START, S_GOTSIGN, S_INF, S_NAN, S_DONE, S_MAYBEHEX,
 		S_DIGITS, S_FRAC, S_EXP, S_EXPDIGITS
 	} state = S_START;
 	wchar_t c;
 	wchar_t decpt;
 	_Bool gotmantdig = 0, ishex = 0;
 
 	mbs = initial_mbs;
 	nconv = mbrtowc(&decpt, localeconv()->decimal_point, MB_CUR_MAX, &mbs);
 	if (nconv == (size_t)-1 || nconv == (size_t)-2)
 		decpt = '.';	/* failsafe */
 
 	/*
 	 * We set commit = p whenever the string we have read so far
 	 * constitutes a valid representation of a floating point
 	 * number by itself.  At some point, the parse will complete
 	 * or fail, and we will ungetc() back to the last commit point.
 	 * To ensure that the file offset gets updated properly, it is
 	 * always necessary to read at least one character that doesn't
 	 * match; thus, we can't short-circuit "infinity" or "nan(...)".
 	 */
 	commit = buf - 1;
 	c = WEOF;
 	for (p = buf; p < end; ) {
 		if ((c = __fgetwc(fp, locale)) == WEOF)
 			break;
 reswitch:
 		switch (state) {
 		case S_START:
 			state = S_GOTSIGN;
 			if (c == '-' || c == '+')
 				break;
 			else
 				goto reswitch;
 		case S_GOTSIGN:
 			switch (c) {
 			case '0':
 				state = S_MAYBEHEX;
 				commit = p;
 				break;
 			case 'I':
 			case 'i':
 				state = S_INF;
 				break;
 			case 'N':
 			case 'n':
 				state = S_NAN;
 				break;
 			default:
 				state = S_DIGITS;
 				goto reswitch;
 			}
 			break;
 		case S_INF:
 			if (infnanpos > 6 ||
 			    (c != "nfinity"[infnanpos] &&
 			     c != "NFINITY"[infnanpos]))
 				goto parsedone;
 			if (infnanpos == 1 || infnanpos == 6)
 				commit = p;	/* inf or infinity */
 			infnanpos++;
 			break;
 		case S_NAN:
 			switch (infnanpos) {
 			case 0:
 				if (c != 'A' && c != 'a')
 					goto parsedone;
 				break;
 			case 1:
 				if (c != 'N' && c != 'n')
 					goto parsedone;
 				else
 					commit = p;
 				break;
 			case 2:
 				if (c != '(')
 					goto parsedone;
 				break;
 			default:
 				if (c == ')') {
 					commit = p;
 					state = S_DONE;
 				} else if (!iswalnum(c) && c != '_')
 					goto parsedone;
 				break;
 			}
 			infnanpos++;
 			break;
 		case S_DONE:
 			goto parsedone;
 		case S_MAYBEHEX:
 			state = S_DIGITS;
 			if (c == 'X' || c == 'x') {
 				ishex = 1;
 				break;
 			} else {	/* we saw a '0', but no 'x' */
 				gotmantdig = 1;
 				goto reswitch;
 			}
 		case S_DIGITS:
 			if ((ishex && iswxdigit(c)) || iswdigit(c))
 				gotmantdig = 1;
 			else {
 				state = S_FRAC;
 				if (c != decpt)
 					goto reswitch;
 			}
 			if (gotmantdig)
 				commit = p;
 			break;
 		case S_FRAC:
 			if (((c == 'E' || c == 'e') && !ishex) ||
 			    ((c == 'P' || c == 'p') && ishex)) {
 				if (!gotmantdig)
 					goto parsedone;
 				else
 					state = S_EXP;
 			} else if ((ishex && iswxdigit(c)) || iswdigit(c)) {
 				commit = p;
 				gotmantdig = 1;
 			} else
 				goto parsedone;
 			break;
 		case S_EXP:
 			state = S_EXPDIGITS;
 			if (c == '-' || c == '+')
 				break;
 			else
 				goto reswitch;
 		case S_EXPDIGITS:
 			if (iswdigit(c))
 				commit = p;
 			else
 				goto parsedone;
 			break;
 		default:
 			abort();
 		}
 		*p++ = c;
 		c = WEOF;
 	}
 
 parsedone:
 	if (c != WEOF)
 		__ungetwc(c, fp, locale);
 	while (commit < --p)
 		__ungetwc(*p, fp, locale);
 	*++commit = '\0';
 	return (commit - buf);
 }
 #endif
Index: head/lib/libc/stdio/vscanf.c
===================================================================
--- head/lib/libc/stdio/vscanf.c	(revision 320471)
+++ head/lib/libc/stdio/vscanf.c	(revision 320472)
@@ -1,66 +1,66 @@
 /*-
  * Copyright (c) 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
  *
  * This code is derived from software contributed to Berkeley by
  * Donn Seeley at UUNET Technologies, Inc.
  *
  * Copyright (c) 2011 The FreeBSD Foundation
  * All rights reserved.
  * Portions of this software were developed by David Chisnall
  * under sponsorship from the FreeBSD Foundation.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
  * 1. Redistributions of source code must retain the above copyright
  *    notice, this list of conditions and the following disclaimer.
  * 2. Redistributions in binary form must reproduce the above copyright
  *    notice, this list of conditions and the following disclaimer in the
  *    documentation and/or other materials provided with the distribution.
  * 3. Neither the name of the University nor the names of its contributors
  *    may be used to endorse or promote products derived from this software
  *    without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
 
 #if defined(LIBC_SCCS) && !defined(lint)
 static char sccsid[] = "@(#)vscanf.c	8.1 (Berkeley) 6/4/93";
 #endif /* LIBC_SCCS and not lint */
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
 #include "namespace.h"
 #include <stdio.h>
 #include "un-namespace.h"
 #include "libc_private.h"
 #include "local.h"
 #include "xlocale_private.h"
 
 int
 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
 vscanf(const char * __restrict fmt, __va_list ap)
 {
 	return vscanf_l(__get_locale(), fmt, ap);
 }