aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKonstantin Belousov <kib@FreeBSD.org>2017-06-29 14:44:17 +0000
committerKonstantin Belousov <kib@FreeBSD.org>2017-06-29 14:44:17 +0000
commitfda0a14f4744c2851766f395775c7531e7c4f7dd (patch)
treebcbf0c774f8341ec74e0dded18a4552c78cdd05c
parentd1372788382ce63271ce58cfe2130d84be40de40 (diff)
downloadsrc-fda0a14f4744c2851766f395775c7531e7c4f7dd.tar.gz
src-fda0a14f4744c2851766f395775c7531e7c4f7dd.zip
Make stdio deferred cancel-safe.
If used with fopen(3)/fdopen(3)-ed FILEs, stdio accurately uses non-cancellable internal versions of the functions, i.e. it seems to be fine with regard to cancellation. But if the funopen(3) and f{r,w}open(3) functions were used to open the FILE, and corresponding user functions create cancellation points (they typically have no other choice), then stdio code at least leaks FILE' lock. The change installs cleanup handler which unlocks FILE. Some minimal restructuring of the code was required to make it use common return place to satisfy hand-rolled pthread_cleanup_pop() requirements. Noted by: eugen Reviewed by: eugen, vangyzen Tested by: pho Sponsored by: The FreeBSD Foundation MFC after: 2 weeks Differential revision: https://reviews.freebsd.org/D11246
Notes
Notes: svn path=/head/; revision=320472
-rw-r--r--lib/libc/stdio/fclose.c8
-rw-r--r--lib/libc/stdio/fflush.c8
-rw-r--r--lib/libc/stdio/fgetc.c4
-rw-r--r--lib/libc/stdio/fgetln.c22
-rw-r--r--lib/libc/stdio/fgets.c22
-rw-r--r--lib/libc/stdio/fgetwc.c4
-rw-r--r--lib/libc/stdio/fgetwln.c13
-rw-r--r--lib/libc/stdio/fgetws.c12
-rw-r--r--lib/libc/stdio/fputc.c4
-rw-r--r--lib/libc/stdio/fputs.c4
-rw-r--r--lib/libc/stdio/fputwc.c4
-rw-r--r--lib/libc/stdio/fputws.c20
-rw-r--r--lib/libc/stdio/fread.c4
-rw-r--r--lib/libc/stdio/freopen.c29
-rw-r--r--lib/libc/stdio/fscanf.c8
-rw-r--r--lib/libc/stdio/fseek.c8
-rw-r--r--lib/libc/stdio/fwrite.c4
-rw-r--r--lib/libc/stdio/getc.c4
-rw-r--r--lib/libc/stdio/getchar.c4
-rw-r--r--lib/libc/stdio/getdelim.c13
-rw-r--r--lib/libc/stdio/gets.c17
-rw-r--r--lib/libc/stdio/local.h26
-rw-r--r--lib/libc/stdio/perror.c4
-rw-r--r--lib/libc/stdio/putc.c4
-rw-r--r--lib/libc/stdio/putchar.c4
-rw-r--r--lib/libc/stdio/puts.c4
-rw-r--r--lib/libc/stdio/putw.c5
-rw-r--r--lib/libc/stdio/refill.c4
-rw-r--r--lib/libc/stdio/scanf.c8
-rw-r--r--lib/libc/stdio/setvbuf.c8
-rw-r--r--lib/libc/stdio/stdio.c8
-rw-r--r--lib/libc/stdio/ungetc.c4
-rw-r--r--lib/libc/stdio/ungetwc.c4
-rw-r--r--lib/libc/stdio/vfprintf.c4
-rw-r--r--lib/libc/stdio/vfscanf.c8
-rw-r--r--lib/libc/stdio/vfwprintf.c4
-rw-r--r--lib/libc/stdio/vfwscanf.c4
-rw-r--r--lib/libc/stdio/vscanf.c4
38 files changed, 185 insertions, 138 deletions
diff --git a/lib/libc/stdio/fclose.c b/lib/libc/stdio/fclose.c
index 24b9b90af985..063ef841f72c 100644
--- a/lib/libc/stdio/fclose.c
+++ b/lib/libc/stdio/fclose.c
@@ -97,7 +97,7 @@ fdclose(FILE *fp, int *fdp)
return (EOF);
}
- FLOCKFILE(fp);
+ FLOCKFILE_CANCELSAFE(fp);
r = 0;
if (fp->_close != __sclose) {
r = EOF;
@@ -115,7 +115,7 @@ fdclose(FILE *fp, int *fdp)
*fdp = fp->_file;
r = cleanfile(fp, false);
}
- FUNLOCKFILE(fp);
+ FUNLOCKFILE_CANCELSAFE();
return (r);
}
@@ -130,9 +130,9 @@ fclose(FILE *fp)
return (EOF);
}
- FLOCKFILE(fp);
+ FLOCKFILE_CANCELSAFE(fp);
r = cleanfile(fp, true);
- FUNLOCKFILE(fp);
+ FUNLOCKFILE_CANCELSAFE();
return (r);
}
diff --git a/lib/libc/stdio/fflush.c b/lib/libc/stdio/fflush.c
index 123167a09129..5ecfc4451f67 100644
--- a/lib/libc/stdio/fflush.c
+++ b/lib/libc/stdio/fflush.c
@@ -56,7 +56,7 @@ fflush(FILE *fp)
if (fp == NULL)
return (_fwalk(sflush_locked));
- FLOCKFILE(fp);
+ FLOCKFILE_CANCELSAFE(fp);
/*
* There is disagreement about the correct behaviour of fflush()
@@ -76,7 +76,7 @@ fflush(FILE *fp)
retval = 0;
else
retval = __sflush(fp);
- FUNLOCKFILE(fp);
+ FUNLOCKFILE_CANCELSAFE();
return (retval);
}
@@ -143,8 +143,8 @@ sflush_locked(FILE *fp)
{
int ret;
- FLOCKFILE(fp);
+ FLOCKFILE_CANCELSAFE(fp);
ret = __sflush(fp);
- FUNLOCKFILE(fp);
+ FUNLOCKFILE_CANCELSAFE();
return (ret);
}
diff --git a/lib/libc/stdio/fgetc.c b/lib/libc/stdio/fgetc.c
index 2ee4d7a78cb5..025a0c2df394 100644
--- a/lib/libc/stdio/fgetc.c
+++ b/lib/libc/stdio/fgetc.c
@@ -46,10 +46,10 @@ int
fgetc(FILE *fp)
{
int retval;
- FLOCKFILE(fp);
+ FLOCKFILE_CANCELSAFE(fp);
/* Orientation set by __sgetc() when buffer is empty. */
/* ORIENT(fp, -1); */
retval = __sgetc(fp);
- FUNLOCKFILE(fp);
+ FUNLOCKFILE_CANCELSAFE();
return (retval);
}
diff --git a/lib/libc/stdio/fgetln.c b/lib/libc/stdio/fgetln.c
index c8e30ee2bf65..1e6b9842bcec 100644
--- a/lib/libc/stdio/fgetln.c
+++ b/lib/libc/stdio/fgetln.c
@@ -85,22 +85,21 @@ char *
fgetln(FILE *fp, size_t *lenp)
{
unsigned char *p;
+ char *ret;
size_t len;
size_t off;
- FLOCKFILE(fp);
+ FLOCKFILE_CANCELSAFE(fp);
ORIENT(fp, -1);
/* make sure there is input */
if (fp->_r <= 0 && __srefill(fp)) {
*lenp = 0;
- FUNLOCKFILE(fp);
- return (NULL);
+ ret = NULL;
+ goto end;
}
/* look for a newline in the input */
if ((p = memchr((void *)fp->_p, '\n', (size_t)fp->_r)) != NULL) {
- char *ret;
-
/*
* Found one. Flag buffer as modified to keep fseek from
* `optimising' a backward seek, in case the user stomps on
@@ -112,8 +111,7 @@ fgetln(FILE *fp, size_t *lenp)
fp->_flags |= __SMOD;
fp->_r -= len;
fp->_p = p;
- FUNLOCKFILE(fp);
- return (ret);
+ goto end;
}
/*
@@ -163,12 +161,14 @@ fgetln(FILE *fp, size_t *lenp)
#ifdef notdef
fp->_lb._base[len] = '\0';
#endif
- FUNLOCKFILE(fp);
- return ((char *)fp->_lb._base);
+ ret = (char *)fp->_lb._base;
+end:
+ FUNLOCKFILE_CANCELSAFE();
+ return (ret);
error:
*lenp = 0; /* ??? */
fp->_flags |= __SERR;
- FUNLOCKFILE(fp);
- return (NULL); /* ??? */
+ ret = NULL;
+ goto end;
}
diff --git a/lib/libc/stdio/fgets.c b/lib/libc/stdio/fgets.c
index a2e39ed3b337..95d0ad997196 100644
--- a/lib/libc/stdio/fgets.c
+++ b/lib/libc/stdio/fgets.c
@@ -53,17 +53,17 @@ char *
fgets(char * __restrict buf, int n, FILE * __restrict fp)
{
size_t len;
- char *s;
+ char *s, *ret;
unsigned char *p, *t;
- FLOCKFILE(fp);
+ FLOCKFILE_CANCELSAFE(fp);
ORIENT(fp, -1);
if (n <= 0) { /* sanity check */
fp->_flags |= __SERR;
errno = EINVAL;
- FUNLOCKFILE(fp);
- return (NULL);
+ ret = NULL;
+ goto end;
}
s = buf;
@@ -76,8 +76,8 @@ fgets(char * __restrict buf, int n, FILE * __restrict fp)
if (__srefill(fp)) {
/* EOF/error: stop with partial or no line */
if (!__sfeof(fp) || s == buf) {
- FUNLOCKFILE(fp);
- return (NULL);
+ ret = NULL;
+ goto end;
}
break;
}
@@ -100,8 +100,8 @@ fgets(char * __restrict buf, int n, FILE * __restrict fp)
fp->_p = t;
(void)memcpy((void *)s, (void *)p, len);
s[len] = 0;
- FUNLOCKFILE(fp);
- return (buf);
+ ret = buf;
+ goto end;
}
fp->_r -= len;
fp->_p += len;
@@ -110,6 +110,8 @@ fgets(char * __restrict buf, int n, FILE * __restrict fp)
n -= len;
}
*s = 0;
- FUNLOCKFILE(fp);
- return (buf);
+ ret = buf;
+end:
+ FUNLOCKFILE_CANCELSAFE();
+ return (ret);
}
diff --git a/lib/libc/stdio/fgetwc.c b/lib/libc/stdio/fgetwc.c
index 3074d441f9f6..5f13e2dd4b74 100644
--- a/lib/libc/stdio/fgetwc.c
+++ b/lib/libc/stdio/fgetwc.c
@@ -52,10 +52,10 @@ fgetwc_l(FILE *fp, locale_t locale)
wint_t r;
FIX_LOCALE(locale);
- FLOCKFILE(fp);
+ FLOCKFILE_CANCELSAFE(fp);
ORIENT(fp, 1);
r = __fgetwc(fp, locale);
- FUNLOCKFILE(fp);
+ FUNLOCKFILE_CANCELSAFE();
return (r);
}
diff --git a/lib/libc/stdio/fgetwln.c b/lib/libc/stdio/fgetwln.c
index 037657c224b0..a29f1f6bfb3b 100644
--- a/lib/libc/stdio/fgetwln.c
+++ b/lib/libc/stdio/fgetwln.c
@@ -45,13 +45,14 @@ wchar_t *fgetwln_l(FILE * __restrict, size_t *, locale_t);
wchar_t *
fgetwln_l(FILE * __restrict fp, size_t *lenp, locale_t locale)
{
+ wchar_t *ret;
wint_t wc;
size_t len;
int savserr;
FIX_LOCALE(locale);
- FLOCKFILE(fp);
+ FLOCKFILE_CANCELSAFE(fp);
ORIENT(fp, 1);
savserr = fp->_flags & __SERR;
@@ -77,14 +78,16 @@ fgetwln_l(FILE * __restrict fp, size_t *lenp, locale_t locale)
if (len == 0)
goto error;
- FUNLOCKFILE(fp);
*lenp = len;
- return ((wchar_t *)fp->_lb._base);
+ ret = (wchar_t *)fp->_lb._base;
+end:
+ FUNLOCKFILE_CANCELSAFE();
+ return (ret);
error:
- FUNLOCKFILE(fp);
*lenp = 0;
- return (NULL);
+ ret = NULL;
+ goto end;
}
wchar_t *
diff --git a/lib/libc/stdio/fgetws.c b/lib/libc/stdio/fgetws.c
index 8513a372835b..83d697ea9581 100644
--- a/lib/libc/stdio/fgetws.c
+++ b/lib/libc/stdio/fgetws.c
@@ -46,14 +46,14 @@ wchar_t *
fgetws_l(wchar_t * __restrict ws, int n, FILE * __restrict fp, locale_t locale)
{
int sret;
- wchar_t *wsp;
+ wchar_t *wsp, *ret;
size_t nconv;
const char *src;
unsigned char *nl;
FIX_LOCALE(locale);
struct xlocale_ctype *l = XLOCALE_CTYPE(locale);
- FLOCKFILE(fp);
+ FLOCKFILE_CANCELSAFE(fp);
ORIENT(fp, 1);
if (n <= 0) {
@@ -113,12 +113,14 @@ fgetws_l(wchar_t * __restrict ws, int n, FILE * __restrict fp, locale_t locale)
goto error;
ok:
*wsp = L'\0';
- FUNLOCKFILE(fp);
+ ret = ws;
+end:
+ FUNLOCKFILE_CANCELSAFE();
return (ws);
error:
- FUNLOCKFILE(fp);
- return (NULL);
+ ret = NULL;
+ goto end;
}
wchar_t *
diff --git a/lib/libc/stdio/fputc.c b/lib/libc/stdio/fputc.c
index 3b6101f92f4d..32c261aa3685 100644
--- a/lib/libc/stdio/fputc.c
+++ b/lib/libc/stdio/fputc.c
@@ -46,10 +46,10 @@ int
fputc(int c, FILE *fp)
{
int retval;
- FLOCKFILE(fp);
+ FLOCKFILE_CANCELSAFE(fp);
/* Orientation set by __sputc() when buffer is full. */
/* ORIENT(fp, -1); */
retval = __sputc(c, fp);
- FUNLOCKFILE(fp);
+ FUNLOCKFILE_CANCELSAFE();
return (retval);
}
diff --git a/lib/libc/stdio/fputs.c b/lib/libc/stdio/fputs.c
index 1f9795a493fa..b10ac52f95d3 100644
--- a/lib/libc/stdio/fputs.c
+++ b/lib/libc/stdio/fputs.c
@@ -59,10 +59,10 @@ fputs(const char * __restrict s, FILE * __restrict fp)
uio.uio_resid = iov.iov_len = strlen(s);
uio.uio_iov = &iov;
uio.uio_iovcnt = 1;
- FLOCKFILE(fp);
+ FLOCKFILE_CANCELSAFE(fp);
ORIENT(fp, -1);
retval = __sfvwrite(fp, &uio);
- FUNLOCKFILE(fp);
+ FUNLOCKFILE_CANCELSAFE();
if (retval == 0)
return (iov.iov_len > INT_MAX ? INT_MAX : iov.iov_len);
return (retval);
diff --git a/lib/libc/stdio/fputwc.c b/lib/libc/stdio/fputwc.c
index 7f0c9109b087..d16886734335 100644
--- a/lib/libc/stdio/fputwc.c
+++ b/lib/libc/stdio/fputwc.c
@@ -74,10 +74,10 @@ fputwc_l(wchar_t wc, FILE *fp, locale_t locale)
wint_t r;
FIX_LOCALE(locale);
- FLOCKFILE(fp);
+ FLOCKFILE_CANCELSAFE(fp);
ORIENT(fp, 1);
r = __fputwc(wc, fp, locale);
- FUNLOCKFILE(fp);
+ FUNLOCKFILE_CANCELSAFE();
return (r);
}
diff --git a/lib/libc/stdio/fputws.c b/lib/libc/stdio/fputws.c
index 41530673c007..19da946054b7 100644
--- a/lib/libc/stdio/fputws.c
+++ b/lib/libc/stdio/fputws.c
@@ -53,11 +53,13 @@ fputws_l(const wchar_t * __restrict ws, FILE * __restrict fp, locale_t locale)
const wchar_t *wsp;
FIX_LOCALE(locale);
struct xlocale_ctype *l = XLOCALE_CTYPE(locale);
+ int ret;
- FLOCKFILE(fp);
+ ret = -1;
+ FLOCKFILE_CANCELSAFE(fp);
ORIENT(fp, 1);
if (prepwrite(fp) != 0)
- goto error;
+ goto end;
uio.uio_iov = &iov;
uio.uio_iovcnt = 1;
iov.iov_base = buf;
@@ -66,17 +68,15 @@ fputws_l(const wchar_t * __restrict ws, FILE * __restrict fp, locale_t locale)
nbytes = l->__wcsnrtombs(buf, &wsp, SIZE_T_MAX, sizeof(buf),
&fp->_mbstate);
if (nbytes == (size_t)-1)
- goto error;
+ goto end;
uio.uio_resid = iov.iov_len = nbytes;
if (__sfvwrite(fp, &uio) != 0)
- goto error;
+ goto end;
} while (wsp != NULL);
- FUNLOCKFILE(fp);
- return (0);
-
-error:
- FUNLOCKFILE(fp);
- return (-1);
+ ret = 0;
+end:
+ FUNLOCKFILE_CANCELSAFE();
+ return (ret);
}
int
diff --git a/lib/libc/stdio/fread.c b/lib/libc/stdio/fread.c
index c24df9914b48..ff1c65b480d8 100644
--- a/lib/libc/stdio/fread.c
+++ b/lib/libc/stdio/fread.c
@@ -54,9 +54,9 @@ fread(void * __restrict buf, size_t size, size_t count, FILE * __restrict fp)
{
size_t ret;
- FLOCKFILE(fp);
+ FLOCKFILE_CANCELSAFE(fp);
ret = __fread(buf, size, count, fp);
- FUNLOCKFILE(fp);
+ FUNLOCKFILE_CANCELSAFE();
return (ret);
}
diff --git a/lib/libc/stdio/freopen.c b/lib/libc/stdio/freopen.c
index e0104c88eef6..3d6cc89b6fa0 100644
--- a/lib/libc/stdio/freopen.c
+++ b/lib/libc/stdio/freopen.c
@@ -68,7 +68,7 @@ freopen(const char * __restrict file, const char * __restrict mode,
return (NULL);
}
- FLOCKFILE(fp);
+ FLOCKFILE_CANCELSAFE(fp);
if (!__sdidinit)
__sinit();
@@ -81,24 +81,24 @@ freopen(const char * __restrict file, const char * __restrict mode,
if (file == NULL) {
/* See comment below regarding freopen() of closed files. */
if (fp->_flags == 0) {
- FUNLOCKFILE(fp);
errno = EINVAL;
- return (NULL);
+ fp = NULL;
+ goto end;
}
if ((dflags = _fcntl(fp->_file, F_GETFL)) < 0) {
sverrno = errno;
fclose(fp);
- FUNLOCKFILE(fp);
errno = sverrno;
- return (NULL);
+ fp = NULL;
+ goto end;
}
/* Work around incorrect O_ACCMODE. */
if ((dflags & O_ACCMODE) != O_RDWR &&
(dflags & (O_ACCMODE | O_EXEC)) != (oflags & O_ACCMODE)) {
fclose(fp);
- FUNLOCKFILE(fp);
errno = EBADF;
- return (NULL);
+ fp = NULL;
+ goto end;
}
if (fp->_flags & __SWR)
(void) __sflush(fp);
@@ -108,9 +108,9 @@ freopen(const char * __restrict file, const char * __restrict mode,
if (_fcntl(fp->_file, F_SETFL, dflags) < 0) {
sverrno = errno;
fclose(fp);
- FUNLOCKFILE(fp);
errno = sverrno;
- return (NULL);
+ fp = NULL;
+ goto end;
}
}
if (oflags & O_TRUNC)
@@ -193,9 +193,9 @@ finish:
if (isopen)
(void) (*fp->_close)(fp->_cookie);
fp->_flags = 0; /* set it free */
- FUNLOCKFILE(fp);
errno = sverrno; /* restore in case _close clobbered */
- return (NULL);
+ fp = NULL;
+ goto end;
}
/*
@@ -221,9 +221,9 @@ finish:
*/
if (f > SHRT_MAX) {
fp->_flags = 0; /* set it free */
- FUNLOCKFILE(fp);
errno = EMFILE;
- return (NULL);
+ fp = NULL;
+ goto end;
}
fp->_flags = flags;
@@ -245,6 +245,7 @@ finish:
fp->_flags2 |= __S2OAP;
(void) _sseek(fp, (fpos_t)0, SEEK_END);
}
- FUNLOCKFILE(fp);
+end:
+ FUNLOCKFILE_CANCELSAFE();
return (fp);
}
diff --git a/lib/libc/stdio/fscanf.c b/lib/libc/stdio/fscanf.c
index 014f09415048..d3e093334482 100644
--- a/lib/libc/stdio/fscanf.c
+++ b/lib/libc/stdio/fscanf.c
@@ -56,10 +56,10 @@ fscanf(FILE * __restrict fp, char const * __restrict fmt, ...)
va_list ap;
va_start(ap, fmt);
- FLOCKFILE(fp);
+ FLOCKFILE_CANCELSAFE(fp);
ret = __svfscanf(fp, __get_locale(), fmt, ap);
va_end(ap);
- FUNLOCKFILE(fp);
+ FUNLOCKFILE_CANCELSAFE();
return (ret);
}
int
@@ -70,9 +70,9 @@ fscanf_l(FILE * __restrict fp, locale_t locale, char const * __restrict fmt, ...
FIX_LOCALE(locale);
va_start(ap, fmt);
- FLOCKFILE(fp);
+ FLOCKFILE_CANCELSAFE(fp);
ret = __svfscanf(fp, locale, fmt, ap);
va_end(ap);
- FUNLOCKFILE(fp);
+ FUNLOCKFILE_CANCELSAFE();
return (ret);
}
diff --git a/lib/libc/stdio/fseek.c b/lib/libc/stdio/fseek.c
index 2897eebf9c88..e933bdabf4d2 100644
--- a/lib/libc/stdio/fseek.c
+++ b/lib/libc/stdio/fseek.c
@@ -60,9 +60,9 @@ fseek(FILE *fp, long offset, int whence)
if (!__sdidinit)
__sinit();
- FLOCKFILE(fp);
+ FLOCKFILE_CANCELSAFE(fp);
ret = _fseeko(fp, (off_t)offset, whence, 1);
- FUNLOCKFILE(fp);
+ FUNLOCKFILE_CANCELSAFE();
if (ret == 0)
errno = serrno;
return (ret);
@@ -78,9 +78,9 @@ fseeko(FILE *fp, off_t offset, int whence)
if (!__sdidinit)
__sinit();
- FLOCKFILE(fp);
+ FLOCKFILE_CANCELSAFE(fp);
ret = _fseeko(fp, offset, whence, 0);
- FUNLOCKFILE(fp);
+ FUNLOCKFILE_CANCELSAFE();
if (ret == 0)
errno = serrno;
return (ret);
diff --git a/lib/libc/stdio/fwrite.c b/lib/libc/stdio/fwrite.c
index 5b57fab0b9e1..41bb4f6b0384 100644
--- a/lib/libc/stdio/fwrite.c
+++ b/lib/libc/stdio/fwrite.c
@@ -82,7 +82,7 @@ fwrite(const void * __restrict buf, size_t size, size_t count, FILE * __restrict
uio.uio_iov = &iov;
uio.uio_iovcnt = 1;
- FLOCKFILE(fp);
+ FLOCKFILE_CANCELSAFE(fp);
ORIENT(fp, -1);
/*
* The usual case is success (__sfvwrite returns 0);
@@ -91,6 +91,6 @@ fwrite(const void * __restrict buf, size_t size, size_t count, FILE * __restrict
*/
if (__sfvwrite(fp, &uio) != 0)
count = (n - uio.uio_resid) / size;
- FUNLOCKFILE(fp);
+ FUNLOCKFILE_CANCELSAFE();
return (count);
}
diff --git a/lib/libc/stdio/getc.c b/lib/libc/stdio/getc.c
index 4963c8ce68e7..ad2df8a72f5d 100644
--- a/lib/libc/stdio/getc.c
+++ b/lib/libc/stdio/getc.c
@@ -49,11 +49,11 @@ int
getc(FILE *fp)
{
int retval;
- FLOCKFILE(fp);
+ FLOCKFILE_CANCELSAFE(fp);
/* Orientation set by __sgetc() when buffer is empty. */
/* ORIENT(fp, -1); */
retval = __sgetc(fp);
- FUNLOCKFILE(fp);
+ FUNLOCKFILE_CANCELSAFE();
return (retval);
}
diff --git a/lib/libc/stdio/getchar.c b/lib/libc/stdio/getchar.c
index 2815072f866e..320f96791ede 100644
--- a/lib/libc/stdio/getchar.c
+++ b/lib/libc/stdio/getchar.c
@@ -52,11 +52,11 @@ int
getchar(void)
{
int retval;
- FLOCKFILE(stdin);
+ FLOCKFILE_CANCELSAFE(stdin);
/* Orientation set by __sgetc() when buffer is empty. */
/* ORIENT(stdin, -1); */
retval = __sgetc(stdin);
- FUNLOCKFILE(stdin);
+ FUNLOCKFILE_CANCELSAFE();
return (retval);
}
diff --git a/lib/libc/stdio/getdelim.c b/lib/libc/stdio/getdelim.c
index 7e0b2e2b6edb..26c608f8d49c 100644
--- a/lib/libc/stdio/getdelim.c
+++ b/lib/libc/stdio/getdelim.c
@@ -112,7 +112,7 @@ getdelim(char ** __restrict linep, size_t * __restrict linecapp, int delim,
u_char *endp;
size_t linelen;
- FLOCKFILE(fp);
+ FLOCKFILE_CANCELSAFE(fp);
ORIENT(fp, -1);
if (linep == NULL || linecapp == NULL) {
@@ -127,9 +127,9 @@ getdelim(char ** __restrict linep, size_t * __restrict linecapp, int delim,
/* If fp is at EOF already, we just need space for the NUL. */
if (!__sfeof(fp) || expandtofit(linep, 1, linecapp))
goto error;
- FUNLOCKFILE(fp);
(*linep)[0] = '\0';
- return (-1);
+ linelen = -1;
+ goto end;
}
linelen = 0;
@@ -150,11 +150,12 @@ getdelim(char ** __restrict linep, size_t * __restrict linecapp, int delim,
done:
/* Invariant: *linep has space for at least linelen+1 bytes. */
(*linep)[linelen] = '\0';
- FUNLOCKFILE(fp);
+end:
+ FUNLOCKFILE_CANCELSAFE();
return (linelen);
error:
fp->_flags |= __SERR;
- FUNLOCKFILE(fp);
- return (-1);
+ linelen = -1;
+ goto end;
}
diff --git a/lib/libc/stdio/gets.c b/lib/libc/stdio/gets.c
index c9438515323a..f31221a74c63 100644
--- a/lib/libc/stdio/gets.c
+++ b/lib/libc/stdio/gets.c
@@ -50,27 +50,30 @@ char *
gets(char *buf)
{
int c;
- char *s;
+ char *s, *ret;
static int warned;
static const char w[] =
"warning: this program uses gets(), which is unsafe.\n";
- FLOCKFILE(stdin);
+ FLOCKFILE_CANCELSAFE(stdin);
ORIENT(stdin, -1);
if (!warned) {
(void) _write(STDERR_FILENO, w, sizeof(w) - 1);
warned = 1;
}
- for (s = buf; (c = __sgetc(stdin)) != '\n';)
+ for (s = buf; (c = __sgetc(stdin)) != '\n'; ) {
if (c == EOF)
if (s == buf) {
- FUNLOCKFILE(stdin);
- return (NULL);
+ ret = NULL;
+ goto end;
} else
break;
else
*s++ = c;
+ }
*s = 0;
- FUNLOCKFILE(stdin);
- return (buf);
+ ret = buf;
+end:
+ FUNLOCKFILE_CANCELSAFE();
+ return (ret);
}
diff --git a/lib/libc/stdio/local.h b/lib/libc/stdio/local.h
index 447391ca0d4f..5c70b73d72b4 100644
--- a/lib/libc/stdio/local.h
+++ b/lib/libc/stdio/local.h
@@ -38,6 +38,9 @@
* $FreeBSD$
*/
+#ifndef _STDIO_LOCAL_H
+#define _STDIO_LOCAL_H
+
#include <sys/types.h> /* for off_t */
#include <pthread.h>
#include <string.h>
@@ -138,3 +141,26 @@ __fgetwc(FILE *fp, locale_t locale)
if ((fp)->_orientation == 0) \
(fp)->_orientation = (o); \
} while (0)
+
+void __stdio_cancel_cleanup(void *);
+#define FLOCKFILE_CANCELSAFE(fp) \
+ { \
+ struct _pthread_cleanup_info __cleanup_info__; \
+ if (__isthreaded) { \
+ _FLOCKFILE(fp); \
+ __pthread_cleanup_push_imp( \
+ __stdio_cancel_cleanup, (fp), \
+ &__cleanup_info__); \
+ } else { \
+ __pthread_cleanup_push_imp( \
+ __stdio_cancel_cleanup, NULL, \
+ &__cleanup_info__); \
+ } \
+ {
+#define FUNLOCKFILE_CANCELSAFE() \
+ (void)0; \
+ } \
+ __pthread_cleanup_pop_imp(1); \
+ }
+
+#endif /* _STDIO_LOCAL_H */
diff --git a/lib/libc/stdio/perror.c b/lib/libc/stdio/perror.c
index 89c079818fb7..15007882b79e 100644
--- a/lib/libc/stdio/perror.c
+++ b/lib/libc/stdio/perror.c
@@ -67,9 +67,9 @@ perror(const char *s)
v++;
v->iov_base = "\n";
v->iov_len = 1;
- FLOCKFILE(stderr);
+ FLOCKFILE_CANCELSAFE(stderr);
__sflush(stderr);
(void)_writev(stderr->_file, iov, (v - iov) + 1);
stderr->_flags &= ~__SOFF;
- FUNLOCKFILE(stderr);
+ FUNLOCKFILE_CANCELSAFE();
}
diff --git a/lib/libc/stdio/putc.c b/lib/libc/stdio/putc.c
index aaffece49d76..c62d13f5ea4e 100644
--- a/lib/libc/stdio/putc.c
+++ b/lib/libc/stdio/putc.c
@@ -49,11 +49,11 @@ int
putc(int c, FILE *fp)
{
int retval;
- FLOCKFILE(fp);
+ FLOCKFILE_CANCELSAFE(fp);
/* Orientation set by __sputc() when buffer is full. */
/* ORIENT(fp, -1); */
retval = __sputc(c, fp);
- FUNLOCKFILE(fp);
+ FUNLOCKFILE_CANCELSAFE();
return (retval);
}
diff --git a/lib/libc/stdio/putchar.c b/lib/libc/stdio/putchar.c
index 756155902f29..1721a986f854 100644
--- a/lib/libc/stdio/putchar.c
+++ b/lib/libc/stdio/putchar.c
@@ -54,11 +54,11 @@ putchar(int c)
int retval;
FILE *so = stdout;
- FLOCKFILE(so);
+ FLOCKFILE_CANCELSAFE(so);
/* Orientation set by __sputc() when buffer is full. */
/* ORIENT(so, -1); */
retval = __sputc(c, so);
- FUNLOCKFILE(so);
+ FUNLOCKFILE_CANCELSAFE();
return (retval);
}
diff --git a/lib/libc/stdio/puts.c b/lib/libc/stdio/puts.c
index 124afc73d600..b5fa01a0c41d 100644
--- a/lib/libc/stdio/puts.c
+++ b/lib/libc/stdio/puts.c
@@ -62,9 +62,9 @@ puts(char const *s)
uio.uio_resid = c + 1;
uio.uio_iov = &iov[0];
uio.uio_iovcnt = 2;
- FLOCKFILE(stdout);
+ FLOCKFILE_CANCELSAFE(stdout);
ORIENT(stdout, -1);
retval = __sfvwrite(stdout, &uio) ? EOF : '\n';
- FUNLOCKFILE(stdout);
+ FUNLOCKFILE_CANCELSAFE();
return (retval);
}
diff --git a/lib/libc/stdio/putw.c b/lib/libc/stdio/putw.c
index ecd5d095de5e..fc1d81c7c25c 100644
--- a/lib/libc/stdio/putw.c
+++ b/lib/libc/stdio/putw.c
@@ -41,6 +41,7 @@ __FBSDID("$FreeBSD$");
#include "un-namespace.h"
#include "fvwrite.h"
#include "libc_private.h"
+#include "local.h"
int
putw(int w, FILE *fp)
@@ -53,8 +54,8 @@ putw(int w, FILE *fp)
uio.uio_resid = iov.iov_len = sizeof(w);
uio.uio_iov = &iov;
uio.uio_iovcnt = 1;
- FLOCKFILE(fp);
+ FLOCKFILE_CANCELSAFE(fp);
retval = __sfvwrite(fp, &uio);
- FUNLOCKFILE(fp);
+ FUNLOCKFILE_CANCELSAFE();
return (retval);
}
diff --git a/lib/libc/stdio/refill.c b/lib/libc/stdio/refill.c
index 71eb2e53dab6..b4b4e015c91f 100644
--- a/lib/libc/stdio/refill.c
+++ b/lib/libc/stdio/refill.c
@@ -53,9 +53,9 @@ lflush(FILE *fp)
int ret = 0;
if ((fp->_flags & (__SLBF|__SWR)) == (__SLBF|__SWR)) {
- FLOCKFILE(fp);
+ FLOCKFILE_CANCELSAFE(fp);
ret = __sflush(fp);
- FUNLOCKFILE(fp);
+ FUNLOCKFILE_CANCELSAFE();
}
return (ret);
}
diff --git a/lib/libc/stdio/scanf.c b/lib/libc/stdio/scanf.c
index e377724ac5be..55aa420fa6f5 100644
--- a/lib/libc/stdio/scanf.c
+++ b/lib/libc/stdio/scanf.c
@@ -56,9 +56,9 @@ scanf(char const * __restrict fmt, ...)
va_list ap;
va_start(ap, fmt);
- FLOCKFILE(stdin);
+ FLOCKFILE_CANCELSAFE(stdin);
ret = __svfscanf(stdin, __get_locale(), fmt, ap);
- FUNLOCKFILE(stdin);
+ FUNLOCKFILE_CANCELSAFE();
va_end(ap);
return (ret);
}
@@ -70,9 +70,9 @@ scanf_l(locale_t locale, char const * __restrict fmt, ...)
FIX_LOCALE(locale);
va_start(ap, fmt);
- FLOCKFILE(stdin);
+ FLOCKFILE_CANCELSAFE(stdin);
ret = __svfscanf(stdin, locale, fmt, ap);
- FUNLOCKFILE(stdin);
+ FUNLOCKFILE_CANCELSAFE();
va_end(ap);
return (ret);
}
diff --git a/lib/libc/stdio/setvbuf.c b/lib/libc/stdio/setvbuf.c
index d39696058616..01db02ea9b64 100644
--- a/lib/libc/stdio/setvbuf.c
+++ b/lib/libc/stdio/setvbuf.c
@@ -63,7 +63,7 @@ setvbuf(FILE * __restrict fp, char * __restrict buf, int mode, size_t size)
if ((mode != _IOFBF && mode != _IOLBF) || (int)size < 0)
return (EOF);
- FLOCKFILE(fp);
+ FLOCKFILE_CANCELSAFE(fp);
/*
* Write current buffer, if any. Discard unread input (including
* ungetc data), cancel line buffering, and free old buffer if
@@ -115,8 +115,7 @@ nbf:
fp->_w = 0;
fp->_bf._base = fp->_p = fp->_nbuf;
fp->_bf._size = 1;
- FUNLOCKFILE(fp);
- return (ret);
+ goto end;
}
flags |= __SMBF;
}
@@ -156,6 +155,7 @@ nbf:
}
__cleanup = _cleanup;
- FUNLOCKFILE(fp);
+end:
+ FUNLOCKFILE_CANCELSAFE();
return (ret);
}
diff --git a/lib/libc/stdio/stdio.c b/lib/libc/stdio/stdio.c
index 5d6fb9ac5644..c92fb4fb0e83 100644
--- a/lib/libc/stdio/stdio.c
+++ b/lib/libc/stdio/stdio.c
@@ -166,3 +166,11 @@ _sseek(FILE *fp, fpos_t offset, int whence)
}
return (ret);
}
+
+void
+__stdio_cancel_cleanup(void * arg)
+{
+
+ if (arg != NULL)
+ _funlockfile((FILE *)arg);
+}
diff --git a/lib/libc/stdio/ungetc.c b/lib/libc/stdio/ungetc.c
index 88c9da555187..a24a5a26ade4 100644
--- a/lib/libc/stdio/ungetc.c
+++ b/lib/libc/stdio/ungetc.c
@@ -94,10 +94,10 @@ ungetc(int c, FILE *fp)
if (!__sdidinit)
__sinit();
- FLOCKFILE(fp);
+ FLOCKFILE_CANCELSAFE(fp);
ORIENT(fp, -1);
ret = __ungetc(c, fp);
- FUNLOCKFILE(fp);
+ FUNLOCKFILE_CANCELSAFE();
return (ret);
}
diff --git a/lib/libc/stdio/ungetwc.c b/lib/libc/stdio/ungetwc.c
index 78bc38d954a0..b47caf4b3248 100644
--- a/lib/libc/stdio/ungetwc.c
+++ b/lib/libc/stdio/ungetwc.c
@@ -76,10 +76,10 @@ ungetwc_l(wint_t wc, FILE *fp, locale_t locale)
wint_t r;
FIX_LOCALE(locale);
- FLOCKFILE(fp);
+ FLOCKFILE_CANCELSAFE(fp);
ORIENT(fp, 1);
r = __ungetwc(wc, fp, locale);
- FUNLOCKFILE(fp);
+ FUNLOCKFILE_CANCELSAFE();
return (r);
}
diff --git a/lib/libc/stdio/vfprintf.c b/lib/libc/stdio/vfprintf.c
index bf45bfb421ed..4779ad7a9902 100644
--- a/lib/libc/stdio/vfprintf.c
+++ b/lib/libc/stdio/vfprintf.c
@@ -274,14 +274,14 @@ vfprintf_l(FILE * __restrict fp, locale_t locale, const char * __restrict fmt0,
int ret;
FIX_LOCALE(locale);
- FLOCKFILE(fp);
+ FLOCKFILE_CANCELSAFE(fp);
/* optimise fprintf(stderr) (and other unbuffered Unix files) */
if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
fp->_file >= 0)
ret = __sbprintf(fp, locale, fmt0, ap);
else
ret = __vfprintf(fp, locale, fmt0, ap);
- FUNLOCKFILE(fp);
+ FUNLOCKFILE_CANCELSAFE();
return (ret);
}
int
diff --git a/lib/libc/stdio/vfscanf.c b/lib/libc/stdio/vfscanf.c
index e49a9e1ed134..8f7c1e81638c 100644
--- a/lib/libc/stdio/vfscanf.c
+++ b/lib/libc/stdio/vfscanf.c
@@ -443,9 +443,9 @@ __vfscanf(FILE *fp, char const *fmt0, va_list ap)
{
int ret;
- FLOCKFILE(fp);
+ FLOCKFILE_CANCELSAFE(fp);
ret = __svfscanf(fp, __get_locale(), fmt0, ap);
- FUNLOCKFILE(fp);
+ FUNLOCKFILE_CANCELSAFE();
return (ret);
}
int
@@ -454,9 +454,9 @@ vfscanf_l(FILE *fp, locale_t locale, char const *fmt0, va_list ap)
int ret;
FIX_LOCALE(locale);
- FLOCKFILE(fp);
+ FLOCKFILE_CANCELSAFE(fp);
ret = __svfscanf(fp, locale, fmt0, ap);
- FUNLOCKFILE(fp);
+ FUNLOCKFILE_CANCELSAFE();
return (ret);
}
diff --git a/lib/libc/stdio/vfwprintf.c b/lib/libc/stdio/vfwprintf.c
index 9a5381d54b9b..f130c14b1a2c 100644
--- a/lib/libc/stdio/vfwprintf.c
+++ b/lib/libc/stdio/vfwprintf.c
@@ -356,14 +356,14 @@ vfwprintf_l(FILE * __restrict fp, locale_t locale,
{
int ret;
FIX_LOCALE(locale);
- FLOCKFILE(fp);
+ FLOCKFILE_CANCELSAFE(fp);
/* optimise fprintf(stderr) (and other unbuffered Unix files) */
if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
fp->_file >= 0)
ret = __sbprintf(fp, locale, fmt0, ap);
else
ret = __vfwprintf(fp, locale, fmt0, ap);
- FUNLOCKFILE(fp);
+ FUNLOCKFILE_CANCELSAFE();
return (ret);
}
int
diff --git a/lib/libc/stdio/vfwscanf.c b/lib/libc/stdio/vfwscanf.c
index 63b5dd1be28a..aedc249f8cff 100644
--- a/lib/libc/stdio/vfwscanf.c
+++ b/lib/libc/stdio/vfwscanf.c
@@ -428,10 +428,10 @@ vfwscanf_l(FILE * __restrict fp, locale_t locale,
int ret;
FIX_LOCALE(locale);
- FLOCKFILE(fp);
+ FLOCKFILE_CANCELSAFE(fp);
ORIENT(fp, 1);
ret = __vfwscanf(fp, locale, fmt, ap);
- FUNLOCKFILE(fp);
+ FUNLOCKFILE_CANCELSAFE();
return (ret);
}
int
diff --git a/lib/libc/stdio/vscanf.c b/lib/libc/stdio/vscanf.c
index 8729c9ca6ba8..309d00c460d2 100644
--- a/lib/libc/stdio/vscanf.c
+++ b/lib/libc/stdio/vscanf.c
@@ -54,9 +54,9 @@ vscanf_l(locale_t locale, const char * __restrict fmt, __va_list ap)
int retval;
FIX_LOCALE(locale);
- FLOCKFILE(stdin);
+ FLOCKFILE_CANCELSAFE(stdin);
retval = __svfscanf(stdin, locale, fmt, ap);
- FUNLOCKFILE(stdin);
+ FUNLOCKFILE_CANCELSAFE();
return (retval);
}
int