I'm currently working on a programm that has a shared memory and semaphores. However I have issues with initializing them. Whenever I wanna open them (whilst having the O_EXCL flag active I keep getting erros. That should mean they are already open when starting but I have no idea how or why.
static sem_t *s1 = NULL;
void initSEM(void)
{
atexit(closeSEM);
s1 = sem_open(SEM_1, O_CREAT | O_EXCL, 0600, 1);
if (s1 == SEM_FAILED)
{
printf("%s", "ERROR: Semaphore 1 could not be opened.");
exit(EXIT_FAILURE);
}
}
void closeSEM(void)
{
if (sem_close(s1) == -1)
{
exit(EXIT_FAILURE);
}
if (sem_close(s2) == -1)
{
exit(EXIT_FAILURE);
}
if (sem_close(s3) == -1)
{
exit(EXIT_FAILURE);
}
if (sem_unlink(SEM_1) == -1)
{
exit(EXIT_FAILURE);
}
if (sem_unlink(SEM_2) == -1)
{
exit(EXIT_FAILURE);
}
if (sem_unlink(SEM_2) == -1)
{
exit(EXIT_FAILURE);
}
}
In my main function I just call this. Same thing for the shared memory. I have no idea why this is happening.
CodePudding user response:
Your code, as written, need fail to open a single semaphore only once, and from then on, will never properly sem_unlink
any of the semaphores, so they continue existing for the next program run.
The sequence of events is:
- At some point in development, a
sem_open
fails for whatever reason - The corresponding
sem_close
then fails, and youexit(EXIT_FAILURE);
rather than performing any remainingsem_close
calls and all of thesem_unlink
calls, so the named semaphore continues to exist - On future runs, all
sem_open
calls withO_CREAT
/O_EXCL
fail (because none of them were unlinked), and the problem is never fixed
The simplest solution is to just remove all the exit(EXIT_FAILURE);
calls (perhaps replacing them with debug logging); if the program otherwise ran to completion successfully, cleanup failures aren't that important; it's more important to ensure all the cleanup is performed than to fail-fast when some cleanup fails.
It might also make sense to register separate atexit
handlers for each named semaphore, and only after sem_open
succeeds for that semaphore, so opening one semaphore doesn't register cleanup functions for all of them, nor does a failed open cause you to schedule cleanup. Doing so would reduce the number of failures expected in common failure cases by limiting cleanup to those cases where it is needed.