| Index: src/client/minidump_file_writer.cc
|
| diff --git a/src/client/minidump_file_writer.cc b/src/client/minidump_file_writer.cc
|
| index 9e905335320acb318cb4a83556eb47e1005ad02b..a1957f324a9c7fb1acf355c3b9a0e873b6110144 100644
|
| --- a/src/client/minidump_file_writer.cc
|
| +++ b/src/client/minidump_file_writer.cc
|
| @@ -44,6 +44,47 @@
|
| #include "third_party/lss/linux_syscall_support.h"
|
| #endif
|
|
|
| +#if defined(__ANDROID__)
|
| +#include <errno.h>
|
| +
|
| +namespace {
|
| +
|
| +bool g_need_ftruncate_workaround = false;
|
| +bool g_checked_need_ftruncate_workaround = false;
|
| +
|
| +void CheckNeedsFTruncateWorkAround(int file) {
|
| + if (g_checked_need_ftruncate_workaround) {
|
| + return;
|
| + }
|
| + g_checked_need_ftruncate_workaround = true;
|
| +
|
| + // Attempt an idempotent truncate that chops off nothing and see if we
|
| + // run into any sort of errors.
|
| + off_t offset = sys_lseek(file, 0, SEEK_END);
|
| + if (offset == -1) {
|
| + // lseek failed. Don't apply work around. It's unlikely that we can write
|
| + // to a minidump with either method.
|
| + return;
|
| + }
|
| +
|
| + int result = ftruncate(file, offset);
|
| + if (result == -1 && errno == EACCES) {
|
| + // It very likely that we are running into the kernel bug in M devices.
|
| + // We are going to deploy the workaround for writing minidump files
|
| + // without uses of ftruncate(). This workaround should be fine even
|
| + // for kernels without the bug.
|
| + // See http://crbug.com/542840 for more details.
|
| + g_need_ftruncate_workaround = true;
|
| + }
|
| +}
|
| +
|
| +bool NeedsFTruncateWorkAround() {
|
| + return g_need_ftruncate_workaround;
|
| +}
|
| +
|
| +} // namespace
|
| +#endif // defined(__ANDROID__)
|
| +
|
| namespace google_breakpad {
|
|
|
| const MDRVA MinidumpFileWriter::kInvalidMDRVA = static_cast<MDRVA>(-1);
|
| @@ -75,15 +116,24 @@ void MinidumpFileWriter::SetFile(const int file) {
|
| assert(file_ == -1);
|
| file_ = file;
|
| close_file_when_destroyed_ = false;
|
| +#if defined(__ANDROID__)
|
| + CheckNeedsFTruncateWorkAround(file);
|
| +#endif
|
| }
|
|
|
| bool MinidumpFileWriter::Close() {
|
| bool result = true;
|
|
|
| if (file_ != -1) {
|
| - if (-1 == ftruncate(file_, position_)) {
|
| +#if defined(__ANDROID__)
|
| + if (!NeedsFTruncateWorkAround() && ftruncate(file_, position_)) {
|
| return false;
|
| }
|
| +#else
|
| + if (ftruncate(file_, position_)) {
|
| + return false;
|
| + }
|
| +#endif
|
| #if defined(__linux__) && __linux__
|
| result = (sys_close(file_) == 0);
|
| #else
|
| @@ -220,6 +270,20 @@ bool MinidumpFileWriter::WriteMemory(const void *src, size_t size,
|
| MDRVA MinidumpFileWriter::Allocate(size_t size) {
|
| assert(size);
|
| assert(file_ != -1);
|
| +#if defined(__ANDROID__)
|
| + if (NeedsFTruncateWorkAround()) {
|
| + // If ftruncate() is not available. We simply increase the size beyond the
|
| + // current file size. sys_write() will expand the file when data is written
|
| + // to it. Because we did not over allocate to fit memory pages, we also
|
| + // do not need to ftruncate() the file once we are done.
|
| + size_ += size;
|
| +
|
| + // We don't need to seek since the file is unchanged.
|
| + MDRVA current_position = position_;
|
| + position_ += static_cast<MDRVA>(size);
|
| + return current_position;
|
| + }
|
| +#endif
|
| size_t aligned_size = (size + 7) & ~7; // 64-bit alignment
|
|
|
| if (position_ + aligned_size > size_) {
|
| @@ -256,14 +320,16 @@ bool MinidumpFileWriter::Copy(MDRVA position, const void *src, ssize_t size) {
|
| #if defined(__linux__) && __linux__
|
| if (sys_lseek(file_, position, SEEK_SET) == static_cast<off_t>(position)) {
|
| if (sys_write(file_, src, size) == size) {
|
| + return true;
|
| + }
|
| + }
|
| #else
|
| if (lseek(file_, position, SEEK_SET) == static_cast<off_t>(position)) {
|
| if (write(file_, src, size) == size) {
|
| -#endif
|
| return true;
|
| }
|
| }
|
| -
|
| +#endif
|
| return false;
|
| }
|
|
|
|
|