Commit a518f634 authored by Yuta Kitamura's avatar Yuta Kitamura Committed by Commit Bot

base: Prevent SIGBUS by preallocating shared memory file.

We have some crash reports for Linux that tell us that processes are
sometimes getting killed with SIGBUS when they write to memory mapped
to shared memory file. The suspected cause is /dev/shm volume getting
full.

This CL is an attempt to avoid this by using posix_fallocate() instead
of ftruncate(), which preallocates memory early and detects disk full
before we write to memory.

The code is only enabled for Linux, because we currently see the symptom
happening only on Linux.

Bug: 1014296
Change-Id: I45c5f4152639a742da689472b73c5e1dd717a2d7
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1895028Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Commit-Queue: Yuta Kitamura <yutak@chromium.org>
Cr-Commit-Position: refs/heads/master@{#712524}
parent 6bdce49d
...@@ -102,8 +102,29 @@ bool SharedMemory::Create(const SharedMemoryCreateOptions& options) { ...@@ -102,8 +102,29 @@ bool SharedMemory::Create(const SharedMemoryCreateOptions& options) {
return false; return false;
const size_t current_size = stat.st_size; const size_t current_size = stat.st_size;
if (current_size != options.size) { if (current_size != options.size) {
#if defined(OS_LINUX)
// When /dev/shm becomes full, writing memory to a mapped region of
// shared memory causes a SIGBUS and kills the process. This is
// inconvenient to us because: (1) we'll get many different crash
// reports at random places that write to shared memory, and (2)
// process killed by SIGBUS confuses many developers. See
// crbug.com/1014296 for details.
//
// Here we preallocate memory by posix_fallocate and detect OOM (ENOSPC)
// early to avoid getting killed by SIGBUS.
// posix_fallocate doesn't use errno and returns the error number
// directly. Thus EINTR is handled manually.
int result;
do {
result = posix_fallocate(fd.get(), 0, options.size);
if (result != 0 && result != EINTR)
return false;
} while (result != 0);
#else
if (HANDLE_EINTR(ftruncate(fd.get(), options.size)) != 0) if (HANDLE_EINTR(ftruncate(fd.get(), options.size)) != 0)
return false; return false;
#endif
} }
requested_size_ = options.size; requested_size_ = options.size;
} else { } else {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment