Store lock files in /dev/shm/osrm -> ~/.osrm/ instead of /tmp to prevent systemd cleanup#7443
Conversation
There was a problem hiding this comment.
Pull request overview
Updates OSRM shared-memory lock file directory selection to avoid /tmp cleanup on long-running Linux systems (e.g., systemd tmpfiles), and adds unit tests covering the new priority order.
Changes:
- Prefer
$HOME/.osrm/for lock files whenSHM_LOCK_DIRis not set, with/tmpas a fallback. - Add unit tests for
getLockDir()behavior (env override, home default, and tmp fallback). - Update
getLockDir()documentation to describe the new priority.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 6 comments.
| File | Description |
|---|---|
src/storage/shared_memory.cpp |
Implements $HOME/.osrm default lock directory and ensures the directory exists. |
include/storage/shared_memory.hpp |
Updates API documentation to reflect lock directory priority and rationale. |
unit_tests/storage/shared_memory.cpp |
Adds unit tests validating getLockDir() selection logic. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| std::filesystem::create_directories(lock_dir); | ||
| return lock_dir; | ||
| } | ||
|
|
||
| return std::filesystem::temp_directory_path(); |
There was a problem hiding this comment.
getLockDir() unconditionally calls std::filesystem::create_directories(lock_dir) and will throw std::filesystem::filesystem_error if $HOME exists but is not writable (or if ~/.osrm is an existing non-directory). This can abort makeSharedMemory() / Storage::Run() rather than falling back to the system temp directory. Consider using the error_code overload (or catching filesystem_error) and falling back to temp_directory_path() with a clear log / exception message suggesting SHM_LOCK_DIR.
| std::filesystem::create_directories(lock_dir); | |
| return lock_dir; | |
| } | |
| return std::filesystem::temp_directory_path(); | |
| std::error_code ec; | |
| const bool exists = std::filesystem::exists(lock_dir, ec); | |
| if (!ec) | |
| { | |
| if (exists) | |
| { | |
| if (std::filesystem::is_directory(lock_dir, ec) && !ec) | |
| { | |
| return lock_dir; | |
| } | |
| util::Log(logWARNING) | |
| << "Cannot use shared memory lock directory " << lock_dir | |
| << ": path exists but is not a directory. Falling back to temporary " | |
| "directory. Set SHM_LOCK_DIR to override."; | |
| } | |
| else | |
| { | |
| std::filesystem::create_directories(lock_dir, ec); | |
| if (!ec) | |
| { | |
| return lock_dir; | |
| } | |
| util::Log(logWARNING) | |
| << "Cannot create shared memory lock directory " << lock_dir << ": " | |
| << ec.message() | |
| << ". Falling back to temporary directory. Set SHM_LOCK_DIR to override."; | |
| } | |
| } | |
| else | |
| { | |
| util::Log(logWARNING) | |
| << "Cannot inspect shared memory lock directory " << lock_dir << ": " | |
| << ec.message() | |
| << ". Falling back to temporary directory. Set SHM_LOCK_DIR to override."; | |
| } | |
| } | |
| std::error_code ec; | |
| auto temp_dir = std::filesystem::temp_directory_path(ec); | |
| if (ec) | |
| { | |
| throw util::exception("Could not determine a shared memory lock directory; " | |
| "failed to use HOME/USERPROFILE and temp_directory_path(): " + | |
| ec.message() + | |
| ". Set SHM_LOCK_DIR to a writable directory." + SOURCE_REF); | |
| } | |
| return temp_dir; |
There was a problem hiding this comment.
added check of error_code
| * Priority: SHM_LOCK_DIR env var > $HOME/.osrm/ > system temp directory. | ||
| * Using $HOME/.osrm/ by default avoids lock files being cleaned by | ||
| * systemd-tmpfiles-clean, which would break shared memory access. |
There was a problem hiding this comment.
The doc comment describes the default as $HOME/.osrm/, but on Windows the implementation also falls back to %USERPROFILE%. Consider updating the comment to reflect the Windows behavior (or avoid platform-specific env var names in the public header).
| * Priority: SHM_LOCK_DIR env var > $HOME/.osrm/ > system temp directory. | |
| * Using $HOME/.osrm/ by default avoids lock files being cleaned by | |
| * systemd-tmpfiles-clean, which would break shared memory access. | |
| * Priority: SHM_LOCK_DIR env var > user-specific .osrm directory in the | |
| * home/profile directory > system temp directory. | |
| * Using a user-specific .osrm directory by default avoids lock files being | |
| * cleaned by system temp directory cleanup tools, which would break shared | |
| * memory access. |
There was a problem hiding this comment.
added "home/profile directory"
| const char *home = std::getenv("HOME"); | ||
| // Skip if HOME is not set (e.g. in containers) | ||
| if (!home) | ||
| return; | ||
|
|
||
| auto lock_dir = getLockDir(); | ||
| auto expected = std::filesystem::path(home) / ".osrm"; | ||
| BOOST_CHECK_EQUAL(lock_dir, expected); | ||
| BOOST_CHECK(std::filesystem::exists(lock_dir)); |
There was a problem hiding this comment.
This test calls getLockDir() using the real HOME and can create ~/.osrm on the developer/CI machine. To keep unit tests hermetic, consider setting HOME to a temporary directory for the duration of the test (and restoring it afterward).
There was a problem hiding this comment.
added auto temp_home = std::filesystem::temp_directory_path() / "osrm-test-home";
| // Ensure SHM_LOCK_DIR is not set | ||
| ::unsetenv("SHM_LOCK_DIR"); | ||
|
|
There was a problem hiding this comment.
The test unsets SHM_LOCK_DIR but does not restore its previous value. If the environment running the test had SHM_LOCK_DIR set, this can leak across test cases and cause order-dependent failures. Consider an RAII env-var guard that saves/restores the previous value.
| auto temp = std::filesystem::temp_directory_path() / "osrm-test-lock-dir"; | ||
| std::filesystem::create_directories(temp); | ||
|
|
||
| ::setenv("SHM_LOCK_DIR", temp.c_str(), 1); | ||
| auto lock_dir = getLockDir(); | ||
| BOOST_CHECK_EQUAL(lock_dir, temp); | ||
|
|
||
| ::unsetenv("SHM_LOCK_DIR"); | ||
| std::filesystem::remove(temp); |
There was a problem hiding this comment.
setenv/unsetenv are POSIX APIs and will not compile on Windows; additionally std::filesystem::path::c_str() is wchar_t* on Windows. If these unit tests are built cross-platform, consider using a small portability wrapper (e.g., _putenv_s on Windows) and passing temp.string().
There was a problem hiding this comment.
fixed, but didn't test windows
|
|
||
| #include <boost/test/unit_test.hpp> | ||
|
|
||
| #include <cstdlib> |
There was a problem hiding this comment.
This file uses std::filesystem and std::string directly but only includes <cstdlib>. Consider adding explicit includes for <filesystem> and <string> to avoid relying on transitive headers.
| #include <cstdlib> | |
| #include <cstdlib> | |
| #include <filesystem> | |
| #include <string> |
ab27c49 to
95088d8
Compare
Lock files used by ftok() to locate System V shared memory segments were
stored in /tmp, which is cleaned by systemd-tmpfiles-clean (Linux, ~10
days) and periodic scripts (macOS, ~3 days). The shared memory segments
themselves survive cleanup as kernel resources, leaving OSRM unable to
reconnect: "lock file does not exist, exiting".
Lock directory is now selected with graceful fallback:
1. SHM_LOCK_DIR env var (explicit override, unchanged)
2. /dev/shm/osrm-<uid>/ (Linux only — RAM-backed tmpfs, never
cleaned, cleared on reboot together with shared memory segments)
3. ~/.osrm/ (macOS, Windows via %USERPROFILE%)
The selected directory is logged at startup. /tmp is no longer used.
95088d8 to
ded37fe
Compare
Issue
Move shared memory lock files out of /tmp to prevent cleanup
Lock files used by ftok() to locate System V shared memory segments were
stored in /tmp, which is cleaned by systemd-tmpfiles-clean (Linux, ~10
days) and periodic scripts (macOS, ~3 days). The shared memory segments
themselves survive cleanup as kernel resources, leaving OSRM unable to
reconnect: "lock file does not exist, exiting".
Lock directory is now selected with graceful fallback:
cleaned, cleared on reboot together with shared memory segments)
The selected directory is logged at startup. /tmp is no longer used.
Validated locally on Mac & Linux:
This change was developed with assistance from Claude (Opus 4.6).
Tasklist
Requirements / Relations
None