aboutsummaryrefslogtreecommitdiffstats
path: root/tests/stdio_ext_test.cpp
diff options
context:
space:
mode:
authorYabin Cui <yabinc@google.com>2015-11-19 13:52:16 -0800
committerYabin Cui <yabinc@google.com>2015-11-20 17:44:26 -0800
commit76144aaa6397fe9e16893882cf59c5c9c0684a66 (patch)
tree366d104ea020fb5d9138d296aac1fcceda383c61 /tests/stdio_ext_test.cpp
parent0ebe2f07c35d4b764bc5d8b5226004e3db46da91 (diff)
downloadandroid_bionic-76144aaa6397fe9e16893882cf59c5c9c0684a66.tar.gz
android_bionic-76144aaa6397fe9e16893882cf59c5c9c0684a66.tar.bz2
android_bionic-76144aaa6397fe9e16893882cf59c5c9c0684a66.zip
Change _stdio_handles_locking into _caller_handles_locking.
It is reported by tsan that funlockfile() can unlock an unlocked mutex. It happens when printf() is called before fopen() or other stdio stuff. As FLOCKFILE(fp) is called before __sinit(), _stdio_handles_locking is false, and _FLOCK(fp) will not be locked. But then cantwrite(fp) in __vfprintf() calls__sinit(), which makes _stdio_handles_locking become true, and FUNLOCKFILE(fp) unlocks _FLOCK(fp). Change _stdio_handles_locking into _caller_handles_locking, so __sinit() won't change its value. Add test due to my previous fault. Bug: 25392375 Change-Id: I483e3c3cdb28da65e62f1fd9615bf58c5403b4dd
Diffstat (limited to 'tests/stdio_ext_test.cpp')
-rw-r--r--tests/stdio_ext_test.cpp22
1 files changed, 22 insertions, 0 deletions
diff --git a/tests/stdio_ext_test.cpp b/tests/stdio_ext_test.cpp
index c95cbbdd5..78725675d 100644
--- a/tests/stdio_ext_test.cpp
+++ b/tests/stdio_ext_test.cpp
@@ -30,6 +30,7 @@
#include <locale.h>
#include "TemporaryFile.h"
+#include "utils.h"
TEST(stdio_ext, __fbufsize) {
FILE* fp = fopen("/proc/version", "r");
@@ -140,3 +141,24 @@ TEST(stdio_ext, __fsetlocking) {
ASSERT_EQ(FSETLOCKING_INTERNAL, __fsetlocking(fp, FSETLOCKING_QUERY));
fclose(fp);
}
+
+static void LockingByCallerHelper(std::atomic<pid_t>* pid) {
+ *pid = gettid();
+ flockfile(stdout);
+ funlockfile(stdout);
+}
+
+TEST(stdio_ext, __fsetlocking_BYCALLER) {
+ // Check if users can use flockfile/funlockfile to protect stdio operations.
+ int old_state = __fsetlocking(stdout, FSETLOCKING_BYCALLER);
+ flockfile(stdout);
+ pthread_t thread;
+ std::atomic<pid_t> pid(0);
+ ASSERT_EQ(0, pthread_create(&thread, nullptr,
+ reinterpret_cast<void* (*)(void*)>(LockingByCallerHelper), &pid));
+ WaitUntilThreadSleep(pid);
+ funlockfile(stdout);
+
+ ASSERT_EQ(0, pthread_join(thread, nullptr));
+ __fsetlocking(stdout, old_state);
+}