summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libc/Android.mk2
-rw-r--r--libc/stdio/findfp.c (renamed from libc/upstream-openbsd/lib/libc/stdio/findfp.c)25
-rw-r--r--tests/stdio_test.cpp17
3 files changed, 34 insertions, 10 deletions
diff --git a/libc/Android.mk b/libc/Android.mk
index 61bdf7e..045556e 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -60,6 +60,7 @@ libc_common_src_files := \
bionic/siginterrupt.c \
bionic/sigsetmask.c \
bionic/system_properties_compat.c \
+ stdio/findfp.c \
stdio/snprintf.c\
stdio/sprintf.c \
@@ -389,7 +390,6 @@ libc_upstream_openbsd_src_files := \
upstream-openbsd/lib/libc/stdio/fgetwc.c \
upstream-openbsd/lib/libc/stdio/fgetws.c \
upstream-openbsd/lib/libc/stdio/fileno.c \
- upstream-openbsd/lib/libc/stdio/findfp.c \
upstream-openbsd/lib/libc/stdio/fprintf.c \
upstream-openbsd/lib/libc/stdio/fpurge.c \
upstream-openbsd/lib/libc/stdio/fputc.c \
diff --git a/libc/upstream-openbsd/lib/libc/stdio/findfp.c b/libc/stdio/findfp.c
index b8c7dc1..0c2ee7c 100644
--- a/libc/upstream-openbsd/lib/libc/stdio/findfp.c
+++ b/libc/stdio/findfp.c
@@ -49,10 +49,8 @@ int __sdidinit;
#define NDYNAMIC 10 /* add ten more whenever necessary */
#define std(flags, file) \
- {0,0,0,flags,file,{0,0},0,__sF+file,__sclose,__sread,__sseek,__swrite, \
- {(unsigned char *)(__sFext+file), 0},NULL,0,{0,0,0},{0},{0,0},0,0}
-/* p r w flags file _bf z cookie close read seek write
- ext */
+ {0,0,0,flags,file,{0},0,__sF+file,__sclose,__sread,__sseek,__swrite, \
+ {(unsigned char *)(__sFext+file), 0},NULL,0,{0},{0},{0},0,0}
/* the usual - (stdin + stdout + stderr) */
static FILE usual[FOPEN_MAX - 3];
@@ -165,17 +163,26 @@ void
__sinit(void)
{
_THREAD_PRIVATE_MUTEX(__sinit_mutex);
- int i;
_THREAD_PRIVATE_MUTEX_LOCK(__sinit_mutex);
- if (__sdidinit)
- goto out; /* bail out if caller lost the race */
- for (i = 0; i < FOPEN_MAX - 3; i++) {
+ if (__sdidinit) {
+ /* bail out if caller lost the race */
+ _THREAD_PRIVATE_MUTEX_UNLOCK(__sinit_mutex);
+ return;
+ }
+
+ /* Initialize stdin/stdout/stderr (for the recursive mutex). http://b/18208568. */
+ for (size_t i = 0; i < 3; ++i) {
+ _FILEEXT_SETUP(__sF+i, __sFext+i);
+ }
+ /* Initialize the pre-allocated (but initially unused) streams. */
+ for (size_t i = 0; i < FOPEN_MAX - 3; ++i) {
_FILEEXT_SETUP(usual+i, usualext+i);
}
+
/* make sure we clean up on exit */
__atexit_register_cleanup(_cleanup); /* conservative */
__sdidinit = 1;
-out:
+
_THREAD_PRIVATE_MUTEX_UNLOCK(__sinit_mutex);
}
diff --git a/tests/stdio_test.cpp b/tests/stdio_test.cpp
index 8c8c235..6a2991f 100644
--- a/tests/stdio_test.cpp
+++ b/tests/stdio_test.cpp
@@ -29,6 +29,23 @@
#include "TemporaryFile.h"
+TEST(stdio, flockfile_18208568_stderr) {
+ // Check that we have a _recursive_ mutex for flockfile.
+ flockfile(stderr);
+ feof(stderr); // We don't care about the result, but this needs to take the lock.
+ funlockfile(stderr);
+}
+
+TEST(stdio, flockfile_18208568_regular) {
+ // We never had a bug for streams other than stdin/stdout/stderr, but test anyway.
+ FILE* fp = fopen("/dev/null", "w");
+ ASSERT_TRUE(fp != NULL);
+ flockfile(fp);
+ feof(fp);
+ funlockfile(fp);
+ fclose(fp);
+}
+
TEST(stdio, tmpfile_fileno_fprintf_rewind_fgets) {
FILE* fp = tmpfile();
ASSERT_TRUE(fp != NULL);