Fixed a miniscule odds race condition found by tsan (Thread sanitizer)

in ThreadedIofile.
Added loop to handle partial writes in ThreadedIoFile.

Change-Id: Ib62855ab849ffbfd00afc5b226dd81d4cd38ff51
This commit is contained in:
Thomas Inskip 2015-11-13 18:43:25 -08:00 committed by Gerrit Code Review
parent 981041a3a8
commit 7b74ca12de
2 changed files with 24 additions and 16 deletions

View File

@ -14,6 +14,9 @@
namespace edash_packager { namespace edash_packager {
namespace media { namespace media {
using base::subtle::NoBarrier_Load;
using base::subtle::NoBarrier_Store;
ThreadedIoFile::ThreadedIoFile(scoped_ptr<File, FileCloser> internal_file, ThreadedIoFile::ThreadedIoFile(scoped_ptr<File, FileCloser> internal_file,
Mode mode, Mode mode,
uint64_t io_cache_size, uint64_t io_cache_size,
@ -70,12 +73,12 @@ int64_t ThreadedIoFile::Read(void* buffer, uint64_t length) {
DCHECK(thread_); DCHECK(thread_);
DCHECK_EQ(kInputMode, mode_); DCHECK_EQ(kInputMode, mode_);
if (internal_file_error_) if (NoBarrier_Load(&eof_) && !cache_.BytesCached())
return internal_file_error_;
if (eof_ && !cache_.BytesCached())
return 0; return 0;
if (NoBarrier_Load(&internal_file_error_))
return NoBarrier_Load(&internal_file_error_);
return cache_.Read(buffer, length); return cache_.Read(buffer, length);
} }
@ -84,8 +87,8 @@ int64_t ThreadedIoFile::Write(const void* buffer, uint64_t length) {
DCHECK(thread_); DCHECK(thread_);
DCHECK_EQ(kOutputMode, mode_); DCHECK_EQ(kOutputMode, mode_);
if (internal_file_error_) if (NoBarrier_Load(&internal_file_error_))
return internal_file_error_; return NoBarrier_Load(&internal_file_error_);
size_ += length; size_ += length;
return cache_.Write(buffer, length); return cache_.Write(buffer, length);
@ -118,8 +121,8 @@ void ThreadedIoFile::RunInInputMode() {
int64_t read_result = internal_file_->Read(&io_buffer_[0], int64_t read_result = internal_file_->Read(&io_buffer_[0],
io_buffer_.size()); io_buffer_.size());
if (read_result <= 0) { if (read_result <= 0) {
eof_ = read_result == 0; NoBarrier_Store(&eof_, read_result == 0);
internal_file_error_ = read_result; NoBarrier_Store(&internal_file_error_, read_result);
cache_.Close(); cache_.Close();
return; return;
} }
@ -153,13 +156,17 @@ void ThreadedIoFile::RunInOutputMode() {
return; return;
} }
} else { } else {
int64_t write_result = internal_file_->Write(&io_buffer_[0], write_bytes); uint64_t bytes_written(0);
if (write_result < 0) { while (bytes_written < write_bytes) {
internal_file_error_ = write_result; int64_t write_result = internal_file_->Write(
cache_.Close(); &io_buffer_[bytes_written], write_bytes - bytes_written);
return; if (write_result < 0) {
NoBarrier_Store(&internal_file_error_, write_result);
cache_.Close();
return;
}
bytes_written += write_result;
} }
CHECK_EQ(write_result, static_cast<int64_t>(write_bytes));
} }
} }
} }

View File

@ -7,6 +7,7 @@
#ifndef PACKAGER_FILE_THREADED_IO_FILE_H_ #ifndef PACKAGER_FILE_THREADED_IO_FILE_H_
#define PACKAGER_FILE_THREADED_IO_FILE_H_ #define PACKAGER_FILE_THREADED_IO_FILE_H_
#include "packager/base/atomicops.h"
#include "packager/base/memory/scoped_ptr.h" #include "packager/base/memory/scoped_ptr.h"
#include "packager/base/synchronization/lock.h" #include "packager/base/synchronization/lock.h"
#include "packager/base/synchronization/waitable_event.h" #include "packager/base/synchronization/waitable_event.h"
@ -58,10 +59,10 @@ class ThreadedIoFile : public File {
std::vector<uint8_t> io_buffer_; std::vector<uint8_t> io_buffer_;
scoped_ptr<ClosureThread> thread_; scoped_ptr<ClosureThread> thread_;
uint64_t size_; uint64_t size_;
bool eof_; base::subtle::Atomic32 eof_;
bool flushing_; bool flushing_;
base::WaitableEvent flush_complete_event_; base::WaitableEvent flush_complete_event_;
int64_t internal_file_error_; base::subtle::Atomic32 internal_file_error_;
DISALLOW_COPY_AND_ASSIGN(ThreadedIoFile); DISALLOW_COPY_AND_ASSIGN(ThreadedIoFile);
}; };