Blog post

Prevent your OpenBSD shared-memory objects from being axed by daily(8)

OpenBSDshared memorydaily

By Marco W. Soijer

Everything is a file, so I could have known. After about a week running continuously — and flawlessly — my shared-memory object seemed to disappear. Existing processes were happily using it, but new processes were waved off with an ENOENT error: no such file or directory.

It needs to go somewhere

There is not a word about it on the OpenBSD man page for managing shared-memory objects, but you can guess that in the back, a file is created. shm_open(3) wants a path name; it returns a file descriptor; you close it with close(2); and after all, everything is a file.

The source shows it: shm_open creates a .shm-file, named as the SHA-256 hash of the shared-memory object's path name, and located in /tmp/.

You would expect to be able to use a shared-memory object for an indefinite time, as long as it is not closed and destroyed. After all, there is no expiration time on shared-memory objects. But there is on temporary files.

Enters: daily(8)

File access and modification times of shared-memory files do not get updated, no matter whether they are dormant for prolonged periods of time, or used intensively. The culprit behind the inaccessible — and actually removed files — is OpenBSD's daily system maintenance script. It takes out all files, except a few explicitly named ones, in /tmp/ that have not been accessed for seven days. And trashes your shared-memory object.

So what to do? You could re-create the shared-memory object regularly, but that does not sound like a good idea. After all, there are various processess working on it. You could change /etc/daily and put in another exception, protecting all .shm files, or at least the one you want to be respected (being a hash, the random-looking 'temporary' filename is deterministic from the chosen path name). But changing daily is discouraged and will not survive a system upgrade. You could change shm_open.c and build your own kernel — even worse.

The easiest way is to touch your file regularly. You can create a cron job for this, refreshing file times twice a week, for example. But in my case, I have a daemon process that works on the shared-memory object at short intervals anyway, so I added a daily call to futimes(shmfd, NULL), in which shmfd is the file descriptor to the shared-memory object.

By the way: semaphores are created the same way. A semaphore is in fact a shared-memory objects with a SHA-256 filename in /tmp/, containing a few integers and pointers. They will probably suffer the same fate. So while I was at it, I created my own semaphore to synchronise access to the shared memory. It requires remarkably simple functionality, for which standard semaphores seem rather excessive in hindsight. But that's for another post.

June 2020

Share this post