linuxinitializationpthreadsmutexshared-memory

How should I initialize pthread mutexes in shared memory, since at program start they can be already initialized?


I'm using shared, robust pthread mutexes to protect some shared memory areas I have in my application. Since my program is managed by a systemd service, it could potentially be restarted, in which case the shared memory segment would have already been existing, and it would contain a valid initialized mutex. Robust mutexes detect if the locking thread has crashed, but I couldn't find anything regarding double initialization if the crashed thread wasn't holding it: how should I initialize a mutex that can potentially had already been initialized?

For what I understood, calling pthread_mutex_init() on an already initialized mutex is UB, pthread_mutex_lock() returns error EOWNERDEAD only if the mutex was being held at crash, but it also returns EINVAL if the mutex hasn't been initialized. So, should I be fine in trying to lock the mutex at startup, and checking whether it returns EINVAL (only if it does, I initialize it)?


EDIT would simply reset all the memory with memset(ptr, 0, size) effectively destroy the mutex, allowing me then to reinitialize it? Or does it leave some traces in the kernel, leaking resources?


EDIT 2 The complete scenario is this: I have one father process and two children, all managed by systemd. The father is responsible to open the shared memory areas (one for each children) and place a mutex in each one. Since this will run on a edge device, during normal functioning it will cleanly exit and shutdown the machine, so no problems there. But I need to keep this running, both for availability reasons and because the father process is the one detecting when it should shutdown the machine (by reading an external signal), so in the systemd service I set up to always restart it. For the children, this is not a problem, since they are not the ones with the code to initialize the mutex, they simply open the shared area. they get restarted too if the father is restarted (not mandatory but useful). This way, however, if there is a restart of the father service, the memory area is still there, with the mutex, and the father will execute the code trying to initialize the mutex.


Solution

  • how should I initialize a mutex that can potentially had already been initialized?

    There is no safe way to do this. You need to know whether to initialize or not.

    Since the "father" alone is responsible for setting up the shared memory and mutex, a reasonable approach would be for it to do this from scratch every time it starts. There are at least two good ways to do this: