From 05f48577e15beb15b72363a36ecb4ca6ec40a6f9 Mon Sep 17 00:00:00 2001 From: anematode Date: Mon, 25 May 2026 11:19:40 +0200 Subject: [PATCH] Fix partial MADV_POPULATE_WRITE Potentially fixes https://github.com/official-stockfish/Stockfish/issues/6846 I'm not a Linux guru but here's my understanding of what's going on, from looking at strace logs. If `/dev/shm` is undersized or too full, `MADV_POPULATE_WRITE` can partially fault in the pages and then return an error. The crash then happens in the second process, on the first read to `header_ptr_->initialized`. There's a TOCTOU between when the region is attachable (the second process can see it in `/dev/shm`) and when we can actually safely read from it. The SIGBUS happens because `/dev/shm` is so full from partially faulted pages that we can't even fault in a single additional page. This didn't happen before because a failed `posix_fallocate` *rolls back any faulted pages*. Then the second process faults in one page (which succeeds), reads a `0` from `header_ptr_->initialized`, declares the region invalid, and continues to try (and fail) to set up its own region. There's still a problem here, methinks, if the process gets killed/interrupted between the failed `madvise` and the `ftruncate`. I think a more robust approach is to create the file anonymously first (to prevent other processes from attaching to it), then `linkat` to publish it atomically, but that would be more implementation work. (Could create a follow-up issue for that as an nice first issue for new contribs?) closes https://github.com/official-stockfish/Stockfish/pull/6852 No functional change --- src/shm_linux.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/shm_linux.h b/src/shm_linux.h index fd5a0d27a..1b8bfe712 100644 --- a/src/shm_linux.h +++ b/src/shm_linux.h @@ -601,6 +601,11 @@ class SharedMemory: public detail::SharedMemoryBase { // If the THP population failed, try with fallocate if (!populated && posix_fallocate(fd_, 0, static_cast(total_size_)) != 0) { + // Release any partially populated pages by a failed MADV_POPULATE_WRITE. + // TODO: Not robust. Need to avoid residual pages if the process + // is terminated between the failed madvise and the ftruncate. + int err = ftruncate(fd_, 0); + (void) err; munmap(mapped_ptr_, total_size_); mapped_ptr_ = nullptr; return false;