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
diff --git a/tests/stdio_test.cpp b/tests/stdio_test.cpp
index 65a942c..c237d6d 100644
--- a/tests/stdio_test.cpp
+++ b/tests/stdio_test.cpp
@@ -29,6 +29,7 @@
#include <locale.h>
#include <string>
+#include <thread>
#include <vector>
#include <android-base/file.h>
@@ -2577,3 +2578,24 @@
ASSERT_LT(0, length);
ASSERT_EQ("/proc/self/fd/2", std::string(path, length));
}
+
+TEST(STDIO_TEST, fread_with_locked_file) {
+ // Reading an unbuffered/line-buffered file from one thread shouldn't block on
+ // files locked on other threads, even if it flushes some line-buffered files.
+ FILE* fp1 = fopen("/dev/zero", "r");
+ ASSERT_TRUE(fp1 != nullptr);
+ flockfile(fp1);
+
+ std::thread([] {
+ for (int mode : { _IONBF, _IOLBF }) {
+ FILE* fp2 = fopen("/dev/zero", "r");
+ ASSERT_TRUE(fp2 != nullptr);
+ setvbuf(fp2, nullptr, mode, 0);
+ ASSERT_EQ('\0', fgetc(fp2));
+ fclose(fp2);
+ }
+ }).join();
+
+ funlockfile(fp1);
+ fclose(fp1);
+}