From c8e263becfa01afecba84edf6a8a18da27a78e89 Mon Sep 17 00:00:00 2001 From: Ryan Prichard Date: Tue, 30 Apr 2019 14:47:34 -0700 Subject: Revert fwalk/sfp locking to fix concurrent reads The locking can fail in a couple of ways: - A concurrent fread from an unbuffered or line-buffered file flushes the output of other line-buffered files, and if _fwalk locks every file, then the fread blocks until other file reads have completed. - __sfp can initialize a file lock while _fwalk is locking/unlocking it. For now, revert to the behavior Bionic had in previous releases. This commit reverts the file locking parts of commit 468efc80da2504f4ae7de8b5e137426d44dda9d7. Bug: http://b/131251441 Bug: http://b/130189834 Test: bionic unit tests Change-Id: I9e20b9cd8ccd14e7962f7308e174f08af72b56c6 (cherry picked from commit c485cdb0249415b8aee5968b2b8854921e152854) --- libc/stdio/stdio.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'libc/stdio/stdio.cpp') diff --git a/libc/stdio/stdio.cpp b/libc/stdio/stdio.cpp index 4cec757e5..91c7689f8 100644 --- a/libc/stdio/stdio.cpp +++ b/libc/stdio/stdio.cpp @@ -106,7 +106,7 @@ FILE* stdin = &__sF[0]; FILE* stdout = &__sF[1]; FILE* stderr = &__sF[2]; -static pthread_mutex_t __stdio_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; +static pthread_mutex_t __stdio_mutex = PTHREAD_MUTEX_INITIALIZER; static uint64_t __get_file_tag(FILE* fp) { // Don't use a tag for the standard streams. @@ -211,21 +211,23 @@ found: } int _fwalk(int (*callback)(FILE*)) { - pthread_mutex_lock(&__stdio_mutex); int result = 0; for (glue* g = &__sglue; g != nullptr; g = g->next) { FILE* fp = g->iobs; for (int n = g->niobs; --n >= 0; ++fp) { - ScopedFileLock sfl(fp); if (fp->_flags != 0 && (fp->_flags & __SIGN) == 0) { result |= (*callback)(fp); } } } - pthread_mutex_unlock(&__stdio_mutex); return result; } +extern "C" __LIBC_HIDDEN__ void __libc_stdio_cleanup(void) { + // Equivalent to fflush(nullptr), but without all the locking since we're shutting down anyway. + _fwalk(__sflush); +} + static FILE* __fopen(int fd, int flags) { #if !defined(__LP64__) if (fd > SHRT_MAX) { @@ -520,6 +522,11 @@ int __sflush(FILE* fp) { return 0; } +int __sflush_locked(FILE* fp) { + ScopedFileLock sfl(fp); + return __sflush(fp); +} + int __sread(void* cookie, char* buf, int n) { FILE* fp = reinterpret_cast(cookie); return TEMP_FAILURE_RETRY(read(fp->_file, buf, n)); @@ -1061,7 +1068,7 @@ int wscanf(const wchar_t* fmt, ...) { } static int fflush_all() { - return _fwalk(__sflush); + return _fwalk(__sflush_locked); } int fflush(FILE* fp) { -- cgit v1.2.3