diff options
| author | Stefan Boberg <[email protected]> | 2026-04-22 09:09:08 +0200 |
|---|---|---|
| committer | GitHub Enterprise <[email protected]> | 2026-04-22 09:09:08 +0200 |
| commit | 9cf0e8812e50f499f401e217c55a442768f03a31 (patch) | |
| tree | f3496804c1c919a676f54f12d518a7b4b947c797 /src/zencore/thread.cpp | |
| parent | changelog version bump (diff) | |
| download | archived-zen-9cf0e8812e50f499f401e217c55a442768f03a31.tar.xz archived-zen-9cf0e8812e50f499f401e217c55a442768f03a31.zip | |
fix NamedEvent ftok() race on Linux/macOS (#1001)
- `ftok()` internally re-`stat()`s the path and fails with `ENOENT` if another owner's destructor unlinks the backing file between our `open()` and `ftok()`; the held fd does not protect against this
- derive the IPC key via `fstat()` on the fd instead, using the same `(ino & 0xffff) | ((dev & 0xff) << 16) | (proj << 24)` formula that glibc and macOS `ftok()` compute internally
- fixes intermittent "Failed to create an SysV IPC key" failures on macOS, where the slower on-disk /tmp widens the race window
Diffstat (limited to 'src/zencore/thread.cpp')
| -rw-r--r-- | src/zencore/thread.cpp | 12 |
1 files changed, 8 insertions, 4 deletions
diff --git a/src/zencore/thread.cpp b/src/zencore/thread.cpp index fd72afaa7..1f4004373 100644 --- a/src/zencore/thread.cpp +++ b/src/zencore/thread.cpp @@ -336,13 +336,17 @@ NamedEvent::NamedEvent(std::string_view EventName) } fchmod(Fd, 0666); - // Use the file path to generate an IPC key - key_t IpcKey = ftok(EventPath.c_str(), 1); - if (IpcKey < 0) + // Derive the IPC key via fstat() on the fd instead of ftok() on the path: + // another owner's destructor can unlink the backing file between our open() + // and ftok(), in which case ftok's internal stat() fails with ENOENT. The + // formula below matches what glibc/macOS ftok() compute internally. + struct stat IpcStat; + if (fstat(Fd, &IpcStat) < 0) { close(Fd); - ThrowLastError("Failed to create an SysV IPC key"); + ThrowLastError("Failed to stat backing file for SysV IPC key"); } + const key_t IpcKey = key_t((IpcStat.st_ino & 0xffff) | ((IpcStat.st_dev & 0xff) << 16) | (1 << 24)); // Use the key to create/open the semaphore int Sem = semget(IpcKey, 1, 0600 | IPC_CREAT); |