summaryrefslogtreecommitdiff
path: root/libc/stdio/stdio.cpp
diff options
context:
space:
mode:
authorRyan Prichard <rprichard@google.com>2019-04-30 14:47:34 -0700
committerRyan Prichard <rprichard@google.com>2019-05-04 00:28:00 -0700
commitc485cdb0249415b8aee5968b2b8854921e152854 (patch)
tree160af7094ea713aa83b280f594e4c834c4316bb3 /libc/stdio/stdio.cpp
parent0cd818a377157326ce326e8a48ea00882d1d1d06 (diff)
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
Diffstat (limited to 'libc/stdio/stdio.cpp')
-rw-r--r--libc/stdio/stdio.cpp17
1 files changed, 12 insertions, 5 deletions
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<FILE*>(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) {