diff options
author | Yabin Cui <yabinc@google.com> | 2015-11-19 13:52:16 -0800 |
---|---|---|
committer | Yabin Cui <yabinc@google.com> | 2015-11-20 17:44:26 -0800 |
commit | 76144aaa6397fe9e16893882cf59c5c9c0684a66 (patch) | |
tree | 366d104ea020fb5d9138d296aac1fcceda383c61 /tests/stdio_ext_test.cpp | |
parent | 0ebe2f07c35d4b764bc5d8b5226004e3db46da91 (diff) | |
download | android_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.cpp | 22 |
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); +} |