diff options
Diffstat (limited to 'libc/stdio/fread.c')
-rw-r--r-- | libc/stdio/fread.c | 29 |
1 files changed, 23 insertions, 6 deletions
diff --git a/libc/stdio/fread.c b/libc/stdio/fread.c index 69c40b3e7..649db17b9 100644 --- a/libc/stdio/fread.c +++ b/libc/stdio/fread.c @@ -39,9 +39,8 @@ static int lflush(FILE *fp) { - if ((fp->_flags & (__SLBF|__SWR)) == (__SLBF|__SWR)) - return (__sflush(fp)); + return (__sflush_locked(fp)); return (0); } @@ -60,6 +59,7 @@ fread(void *buf, size_t size, size_t count, FILE *fp) */ if ((resid = count * size) == 0) return (0); + FLOCKFILE(fp); if (fp->_r < 0) fp->_r = 0; total = resid; @@ -79,20 +79,25 @@ fread(void *buf, size_t size, size_t count, FILE *fp) fp->_r = 0; /* largely a convenience for callers */ /* SysV does not make this test; take it out for compatibility */ - if (fp->_flags & __SEOF) + if (fp->_flags & __SEOF) { + FUNLOCKFILE(fp); 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; + FUNLOCKFILE(fp); + errno = EBADF; return (EOF); } /* switch to reading */ if (fp->_flags & __SWR) { - if (__sflush(fp)) + if (__sflush(fp)) { + FUNLOCKFILE(fp); return (EOF); + } fp->_flags &= ~__SWR; fp->_w = 0; fp->_lbfsize = 0; @@ -116,8 +121,16 @@ fread(void *buf, size_t size, size_t count, FILE *fp) * standard. */ - if (fp->_flags & (__SLBF|__SNBF)) + if (fp->_flags & (__SLBF|__SNBF)) { + /* Ignore this file in _fwalk to 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); + } while (resid > 0) { int len = (*fp->_read)(fp->_cookie, p, resid ); @@ -128,11 +141,13 @@ fread(void *buf, size_t size, size_t count, FILE *fp) else { fp->_flags |= __SERR; } + FUNLOCKFILE(fp); return ((total - resid) / size); } p += len; resid -= len; } + FUNLOCKFILE(fp); return (count); } else @@ -146,6 +161,7 @@ fread(void *buf, size_t size, size_t count, FILE *fp) resid -= r; if (__srefill(fp)) { /* no more input: return partial result */ + FUNLOCKFILE(fp); return ((total - resid) / size); } } @@ -154,5 +170,6 @@ fread(void *buf, size_t size, size_t count, FILE *fp) (void)memcpy((void *)p, (void *)fp->_p, resid); fp->_r -= resid; fp->_p += resid; + FUNLOCKFILE(fp); return (count); } |