Fix issue 474: a race between the f*_unlocked() STDIO calls in

env_posix.cc and concurrent application calls to fflush(NULL).

The fix is to avoid using stdio in env_posix.cc but add our own
buffering where we need it.

Added a test to reproduce the bug.

Added a test for Env reads/writes.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=170738066
This commit is contained in:
sanjay
2017-10-02 12:37:45 -07:00
committed by Victor Costan
parent bcd9a8ea4a
commit 7e12c00ecf
3 changed files with 156 additions and 47 deletions

View File

@@ -6,6 +6,7 @@
#include "port/port.h"
#include "util/testharness.h"
#include "util/testutil.h"
namespace leveldb {
@@ -27,6 +28,55 @@ static void SetBool(void* ptr) {
reinterpret_cast<port::AtomicPointer*>(ptr)->NoBarrier_Store(ptr);
}
TEST(EnvTest, ReadWrite) {
Random rnd(test::RandomSeed());
// Get file to use for testing.
std::string test_dir;
ASSERT_OK(env_->GetTestDirectory(&test_dir));
std::string test_file_name = test_dir + "/open_on_read.txt";
WritableFile* wfile_tmp;
ASSERT_OK(env_->NewWritableFile(test_file_name, &wfile_tmp));
std::unique_ptr<WritableFile> wfile(wfile_tmp);
// Fill a file with data generated via a sequence of randomly sized writes.
static const size_t kDataSize = 10 * 1048576;
std::string data;
while (data.size() < kDataSize) {
int len = rnd.Skewed(18); // Up to 2^18 - 1, but typically much smaller
std::string r;
test::RandomString(&rnd, len, &r);
ASSERT_OK(wfile->Append(r));
data += r;
if (rnd.OneIn(10)) {
ASSERT_OK(wfile->Flush());
}
}
ASSERT_OK(wfile->Sync());
ASSERT_OK(wfile->Close());
wfile.reset();
// Read all data using a sequence of randomly sized reads.
SequentialFile* rfile_tmp;
ASSERT_OK(env_->NewSequentialFile(test_file_name, &rfile_tmp));
std::unique_ptr<SequentialFile> rfile(rfile_tmp);
std::string read_result;
std::string scratch;
while (read_result.size() < data.size()) {
int len = std::min<int>(rnd.Skewed(18), data.size() - read_result.size());
scratch.resize(std::max(len, 1)); // at least 1 so &scratch[0] is legal
Slice read;
ASSERT_OK(rfile->Read(len, &read, &scratch[0]));
if (len > 0) {
ASSERT_GT(read.size(), 0);
}
ASSERT_LE(read.size(), len);
read_result.append(read.data(), read.size());
}
ASSERT_EQ(read_result, data);
}
TEST(EnvTest, RunImmediately) {
port::AtomicPointer called (NULL);
env_->Schedule(&SetBool, &called);