mirror of
https://github.com/chromium/crashpad.git
synced 2024-12-27 15:32:10 +08:00
fuchsia: Compile out LoggingLock/UnlockFile, add DCHECKs to Settings
Fuchsia does not currently support any sort of file locking. Until a lock server can be implemented, compile out the calls to flock(). In the one current non-test user of locking (Settings) add a pseudo-implementation that will DCHECK if there is ever contention on the lock. Bug: crashpad:217, crashpad:196 Change-Id: Ifdf7e00886ad7e7778745f1ae8f0ce2a86f0ae3b Reviewed-on: https://chromium-review.googlesource.com/924312 Commit-Queue: Scott Graham <scottmg@chromium.org> Reviewed-by: Mark Mentovai <mark@chromium.org>
This commit is contained in:
parent
10222b1236
commit
5cb869392e
@ -20,10 +20,55 @@
|
|||||||
|
|
||||||
#include "base/logging.h"
|
#include "base/logging.h"
|
||||||
#include "base/posix/eintr_wrapper.h"
|
#include "base/posix/eintr_wrapper.h"
|
||||||
|
#include "util/file/filesystem.h"
|
||||||
#include "util/numeric/in_range_cast.h"
|
#include "util/numeric/in_range_cast.h"
|
||||||
|
|
||||||
namespace crashpad {
|
namespace crashpad {
|
||||||
|
|
||||||
|
#if defined(OS_FUCHSIA)
|
||||||
|
|
||||||
|
Settings::ScopedLockedFileHandle::ScopedLockedFileHandle()
|
||||||
|
: handle_(kInvalidFileHandle), lockfile_path_() {
|
||||||
|
}
|
||||||
|
|
||||||
|
Settings::ScopedLockedFileHandle::ScopedLockedFileHandle(
|
||||||
|
FileHandle handle,
|
||||||
|
const base::FilePath& lockfile_path)
|
||||||
|
: handle_(handle), lockfile_path_(lockfile_path) {
|
||||||
|
}
|
||||||
|
|
||||||
|
Settings::ScopedLockedFileHandle::ScopedLockedFileHandle(
|
||||||
|
ScopedLockedFileHandle&& other)
|
||||||
|
: handle_(other.handle_), lockfile_path_(other.lockfile_path_) {
|
||||||
|
other.handle_ = kInvalidFileHandle;
|
||||||
|
other.lockfile_path_ = base::FilePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
Settings::ScopedLockedFileHandle& Settings::ScopedLockedFileHandle::operator=(
|
||||||
|
ScopedLockedFileHandle&& other) {
|
||||||
|
handle_ = other.handle_;
|
||||||
|
lockfile_path_ = other.lockfile_path_;
|
||||||
|
|
||||||
|
other.handle_ = kInvalidFileHandle;
|
||||||
|
other.lockfile_path_ = base::FilePath();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Settings::ScopedLockedFileHandle::~ScopedLockedFileHandle() {
|
||||||
|
Destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Settings::ScopedLockedFileHandle::Destroy() {
|
||||||
|
if (handle_ != kInvalidFileHandle) {
|
||||||
|
CheckedCloseFile(handle_);
|
||||||
|
}
|
||||||
|
if (!lockfile_path_.empty()) {
|
||||||
|
DCHECK(LoggingRemoveFile(lockfile_path_));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#else // OS_FUCHSIA
|
||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
// static
|
// static
|
||||||
@ -36,6 +81,8 @@ void ScopedLockedFileHandleTraits::Free(FileHandle handle) {
|
|||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
|
||||||
|
#endif // OS_FUCHSIA
|
||||||
|
|
||||||
struct Settings::Data {
|
struct Settings::Data {
|
||||||
static const uint32_t kSettingsMagic = 'CPds';
|
static const uint32_t kSettingsMagic = 'CPds';
|
||||||
static const uint32_t kSettingsVersion = 1;
|
static const uint32_t kSettingsVersion = 1;
|
||||||
@ -142,18 +189,33 @@ bool Settings::SetLastUploadAttemptTime(time_t time) {
|
|||||||
// static
|
// static
|
||||||
Settings::ScopedLockedFileHandle Settings::MakeScopedLockedFileHandle(
|
Settings::ScopedLockedFileHandle Settings::MakeScopedLockedFileHandle(
|
||||||
FileHandle file,
|
FileHandle file,
|
||||||
FileLocking locking) {
|
FileLocking locking,
|
||||||
|
const base::FilePath& file_path) {
|
||||||
ScopedFileHandle scoped(file);
|
ScopedFileHandle scoped(file);
|
||||||
|
#if defined(OS_FUCHSIA)
|
||||||
|
base::FilePath lockfile_path(file_path.value() + ".__lock__");
|
||||||
|
if (scoped.is_valid()) {
|
||||||
|
ScopedFileHandle lockfile_scoped(
|
||||||
|
LoggingOpenFileForWrite(lockfile_path,
|
||||||
|
FileWriteMode::kCreateOrFail,
|
||||||
|
FilePermissions::kWorldReadable));
|
||||||
|
// This is a lightweight attempt to try to catch racy behavior.
|
||||||
|
DCHECK(lockfile_scoped.is_valid());
|
||||||
|
return ScopedLockedFileHandle(scoped.release(), lockfile_path);
|
||||||
|
}
|
||||||
|
return ScopedLockedFileHandle(scoped.release(), base::FilePath());
|
||||||
|
#else
|
||||||
if (scoped.is_valid()) {
|
if (scoped.is_valid()) {
|
||||||
if (!LoggingLockFile(scoped.get(), locking))
|
if (!LoggingLockFile(scoped.get(), locking))
|
||||||
scoped.reset();
|
scoped.reset();
|
||||||
}
|
}
|
||||||
return ScopedLockedFileHandle(scoped.release());
|
return ScopedLockedFileHandle(scoped.release());
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
Settings::ScopedLockedFileHandle Settings::OpenForReading() {
|
Settings::ScopedLockedFileHandle Settings::OpenForReading() {
|
||||||
return MakeScopedLockedFileHandle(LoggingOpenFileForRead(file_path()),
|
return MakeScopedLockedFileHandle(
|
||||||
FileLocking::kShared);
|
LoggingOpenFileForRead(file_path()), FileLocking::kShared, file_path());
|
||||||
}
|
}
|
||||||
|
|
||||||
Settings::ScopedLockedFileHandle Settings::OpenForReadingAndWriting(
|
Settings::ScopedLockedFileHandle Settings::OpenForReadingAndWriting(
|
||||||
@ -169,7 +231,8 @@ Settings::ScopedLockedFileHandle Settings::OpenForReadingAndWriting(
|
|||||||
file_path(), mode, FilePermissions::kWorldReadable);
|
file_path(), mode, FilePermissions::kWorldReadable);
|
||||||
}
|
}
|
||||||
|
|
||||||
return MakeScopedLockedFileHandle(handle, FileLocking::kExclusive);
|
return MakeScopedLockedFileHandle(
|
||||||
|
handle, FileLocking::kExclusive, file_path());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Settings::OpenAndReadSettings(Data* out_data) {
|
bool Settings::OpenAndReadSettings(Data* out_data) {
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include "base/files/file_path.h"
|
#include "base/files/file_path.h"
|
||||||
#include "base/macros.h"
|
#include "base/macros.h"
|
||||||
#include "base/scoped_generic.h"
|
#include "base/scoped_generic.h"
|
||||||
|
#include "build/build_config.h"
|
||||||
#include "util/file/file_io.h"
|
#include "util/file/file_io.h"
|
||||||
#include "util/misc/initialization_state.h"
|
#include "util/misc/initialization_state.h"
|
||||||
#include "util/misc/uuid.h"
|
#include "util/misc/uuid.h"
|
||||||
@ -114,11 +115,45 @@ class Settings {
|
|||||||
struct Data;
|
struct Data;
|
||||||
|
|
||||||
// This must be constructed with MakeScopedLockedFileHandle(). It both unlocks
|
// This must be constructed with MakeScopedLockedFileHandle(). It both unlocks
|
||||||
// and closes the file on destruction.
|
// and closes the file on destruction. Note that on Fuchsia, this handle DOES
|
||||||
|
// NOT offer correct operation, only an attempt to DCHECK if racy behavior is
|
||||||
|
// detected.
|
||||||
|
#if defined(OS_FUCHSIA)
|
||||||
|
struct ScopedLockedFileHandle {
|
||||||
|
public:
|
||||||
|
ScopedLockedFileHandle();
|
||||||
|
ScopedLockedFileHandle(FileHandle handle,
|
||||||
|
const base::FilePath& lockfile_path);
|
||||||
|
ScopedLockedFileHandle(ScopedLockedFileHandle&& other);
|
||||||
|
ScopedLockedFileHandle& operator=(ScopedLockedFileHandle&& other);
|
||||||
|
~ScopedLockedFileHandle();
|
||||||
|
|
||||||
|
// These mirror the non-Fuchsia ScopedLockedFileHandle via ScopedGeneric so
|
||||||
|
// that calling code can pretend this implementation is the same.
|
||||||
|
bool is_valid() const { return handle_ != kInvalidFileHandle; }
|
||||||
|
FileHandle get() { return handle_; }
|
||||||
|
void reset() {
|
||||||
|
Destroy();
|
||||||
|
handle_ = kInvalidFileHandle;
|
||||||
|
lockfile_path_ = base::FilePath();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void Destroy();
|
||||||
|
|
||||||
|
FileHandle handle_;
|
||||||
|
base::FilePath lockfile_path_;
|
||||||
|
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(ScopedLockedFileHandle);
|
||||||
|
};
|
||||||
|
#else // OS_FUCHSIA
|
||||||
using ScopedLockedFileHandle =
|
using ScopedLockedFileHandle =
|
||||||
base::ScopedGeneric<FileHandle, internal::ScopedLockedFileHandleTraits>;
|
base::ScopedGeneric<FileHandle, internal::ScopedLockedFileHandleTraits>;
|
||||||
static ScopedLockedFileHandle MakeScopedLockedFileHandle(FileHandle file,
|
#endif // OS_FUCHSIA
|
||||||
FileLocking locking);
|
static ScopedLockedFileHandle MakeScopedLockedFileHandle(
|
||||||
|
FileHandle file,
|
||||||
|
FileLocking locking,
|
||||||
|
const base::FilePath& file_path);
|
||||||
|
|
||||||
// Opens the settings file for reading. On error, logs a message and returns
|
// Opens the settings file for reading. On error, logs a message and returns
|
||||||
// the invalid handle.
|
// the invalid handle.
|
||||||
|
@ -404,6 +404,11 @@ FileHandle LoggingOpenFileForReadAndWrite(const base::FilePath& path,
|
|||||||
FileWriteMode mode,
|
FileWriteMode mode,
|
||||||
FilePermissions permissions);
|
FilePermissions permissions);
|
||||||
|
|
||||||
|
// Fuchsia does not currently support any sort of file locking. See
|
||||||
|
// https://crashpad.chromium.org/bug/196 and
|
||||||
|
// https://crashpad.chromium.org/bug/217.
|
||||||
|
#if !defined(OS_FUCHSIA)
|
||||||
|
|
||||||
//! \brief Locks the given \a file using `flock()` on POSIX or `LockFileEx()` on
|
//! \brief Locks the given \a file using `flock()` on POSIX or `LockFileEx()` on
|
||||||
//! Windows.
|
//! Windows.
|
||||||
//!
|
//!
|
||||||
@ -433,6 +438,8 @@ bool LoggingLockFile(FileHandle file, FileLocking locking);
|
|||||||
//! \return `true` on success, or `false` and a message will be logged.
|
//! \return `true` on success, or `false` and a message will be logged.
|
||||||
bool LoggingUnlockFile(FileHandle file);
|
bool LoggingUnlockFile(FileHandle file);
|
||||||
|
|
||||||
|
#endif // !OS_FUCHSIA
|
||||||
|
|
||||||
//! \brief Wraps `lseek()` or `SetFilePointerEx()`. Logs an error if the
|
//! \brief Wraps `lseek()` or `SetFilePointerEx()`. Logs an error if the
|
||||||
//! operation fails.
|
//! operation fails.
|
||||||
//!
|
//!
|
||||||
|
@ -157,18 +157,7 @@ FileHandle LoggingOpenFileForReadAndWrite(const base::FilePath& path,
|
|||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(OS_FUCHSIA)
|
#if !defined(OS_FUCHSIA)
|
||||||
int flock(int, int) {
|
|
||||||
// TODO(scottmg): https://crashpad.chromium.org/bug/196:
|
|
||||||
// This was removed from the libc of Fuchsia recently. A new implementation of
|
|
||||||
// Settings is being worked on that doesn't require flock(), but until then,
|
|
||||||
// it's more useful to have it link, but fail at runtime than it is to exclude
|
|
||||||
// a lot of code (Settings, which requires excludes the CrashReportDatabase,
|
|
||||||
// which requires excluding a variety of tests, the handler, and so on.).
|
|
||||||
NOTREACHED();
|
|
||||||
return ENOSYS;
|
|
||||||
}
|
|
||||||
#endif // OS_FUCHSIA
|
|
||||||
|
|
||||||
bool LoggingLockFile(FileHandle file, FileLocking locking) {
|
bool LoggingLockFile(FileHandle file, FileLocking locking) {
|
||||||
int operation = (locking == FileLocking::kShared) ? LOCK_SH : LOCK_EX;
|
int operation = (locking == FileLocking::kShared) ? LOCK_SH : LOCK_EX;
|
||||||
@ -183,6 +172,8 @@ bool LoggingUnlockFile(FileHandle file) {
|
|||||||
return rv == 0;
|
return rv == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // !OS_FUCHSIA
|
||||||
|
|
||||||
FileOffset LoggingSeekFile(FileHandle file, FileOffset offset, int whence) {
|
FileOffset LoggingSeekFile(FileHandle file, FileOffset offset, int whence) {
|
||||||
off_t rv = lseek(file, offset, whence);
|
off_t rv = lseek(file, offset, whence);
|
||||||
PLOG_IF(ERROR, rv < 0) << "lseek";
|
PLOG_IF(ERROR, rv < 0) << "lseek";
|
||||||
|
@ -523,6 +523,11 @@ TEST(FileIO, FileShareMode_Write_Write) {
|
|||||||
FileShareModeTest(ReadOrWrite::kWrite, ReadOrWrite::kWrite);
|
FileShareModeTest(ReadOrWrite::kWrite, ReadOrWrite::kWrite);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fuchsia does not currently support any sort of file locking. See
|
||||||
|
// https://crashpad.chromium.org/bug/196 and
|
||||||
|
// https://crashpad.chromium.org/bug/217.
|
||||||
|
#if !defined(OS_FUCHSIA)
|
||||||
|
|
||||||
TEST(FileIO, MultipleSharedLocks) {
|
TEST(FileIO, MultipleSharedLocks) {
|
||||||
ScopedTempDir temp_dir;
|
ScopedTempDir temp_dir;
|
||||||
base::FilePath shared_file =
|
base::FilePath shared_file =
|
||||||
@ -648,6 +653,8 @@ TEST(FileIO, SharedVsExclusives) {
|
|||||||
LockingTest(FileLocking::kShared, FileLocking::kExclusive);
|
LockingTest(FileLocking::kShared, FileLocking::kExclusive);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // !OS_FUCHSIA
|
||||||
|
|
||||||
TEST(FileIO, FileSizeByHandle) {
|
TEST(FileIO, FileSizeByHandle) {
|
||||||
EXPECT_EQ(LoggingFileSizeByHandle(kInvalidFileHandle), -1);
|
EXPECT_EQ(LoggingFileSizeByHandle(kInvalidFileHandle), -1);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user