When to Call Sem_Unlink()

Why We unlink semaphores before we initializes them?

why we delete a semaphore before initialize it even though the initialization might be the first one.

Because named semaphores such as are created by sem_open() have kernel persistence. That's part of the point of naming them. They live until either

  • they are unlinked and no processes remain that have them open, OR
  • the system is shut down.

If you want to be sure you are creating a new (named) semaphore instead of opening an existing one then unlinking the name before the sem_open() call makes that pretty likely. If you want to be certain, however, then you should also add O_EXCL to the flags. That will cause sem_open() to fail if a semaphore with the given name already exists, such as if another process created one between the sem_unlink() and the sem_open().

Note also that semaphore names should begin with a / (see sem_overview(7)). Some libraries don't enforce that, but you should not gratuitously introduce a portability issue by omitting it.

On the other hand, if you want a semaphore for a single process only, whose lifetime is bounded by its host process, then you are just making life hard on yourself by using named semaphores. You would be better off in that case with anonymous ones, declared as objects of type sem_t and initialized via the sem_init() function instead of sem_open(). That would moot all the persistence and unlinking questions.

Doubts regarding Named Semaphore in C Linux

http://linux.die.net/man/7/sem_overview

"POSIX named semaphores have kernel persistence: if not removed by sem_unlink(3), a semaphore will exist until the system is shut down."

Why is my semaphore on a forked process not being released?

This problem was occurring ultimately because I was calling sem_unlink on the POSIX semaphore before doing a wait on it in the forked process. Calling sem_unlink causes the semaphore to be removed when all file descriptors have called sem_close on the semaphore. This, in essence, prevented my child process from being able to use that instance and be released at all.

This only works sometimes because there is a base assumption that the child is already waiting to be released by the time we call release_child. This is not guaranteed and was the reason that this was working sometimes and not all the time. If we call release_child before the child has called sem_wait then we remove the semaphore completely and the child creates their own version of the semaphore that never gets posted to.

By moving the unlink call after the if statement in the first set of code, I prevented the child process from removing the semaphore before waiting on it. Also, by removing O_CREAT flag from the sem_open in the release_child and wait_until_released functions and the sem_unlink from the release_child function, I prevented the child from creating their own semaphore.

I wanted to record the behavior that I was seeing though because that was what really caused me problems. In the middle of debugging and fixing this problem I learned that if the parent creates the semaphore but doesn't close it, the child was calling the sem_unlink and creating it's own version with the same name. This caused me to believe that the original semaphore was still there but that the sem_post and/or sem_wait were not working.

So just be aware of your post, wait, close, and unlink calls when you are doing semaphores. Especially when it comes to forked processes!!

Semaphores and shared memory already opened / Problem with O_EXCL flag

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:

  1. At some point in development, a sem_open fails for whatever reason
  2. The corresponding sem_close then fails, and you exit(EXIT_FAILURE); rather than performing any remaining sem_close calls and all of the sem_unlink calls, so the named semaphore continues to exist
  3. On future runs, all sem_open calls with O_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.

Named semaphores in C are not deleted after a signal handler call

As @Jonathan said, the SIGTERM signal I use does terminate the process that should clean up the semaphores. By ignoring the signal in the parent process, everything works well.

sem_open fails on second run of program despite successful sem_close call

I need to use both sem_close and sem_unlink. This was mentioned in sem_init on OS X, but I missed the significance. This answer helps detail when to use each function. To summerize:

sem_close only frees the resources used by the semaphore. A closed semaphore persists and can be reopened.

sem_unlink marks the semaphore to be destroyed when all processes stop using it.

As @JohnBollinger added in the comments,

If you need the semaphore only for the duration of one run of one
program, then you should consider unlinking it (via sem_unlink())
immediately after creating it. You can then continue to use it until
you close it, but it will not block other instances of the program
from using the same semaphore name. Moreover, since open semaphores
are closed but not automatically unlinked when the program exits, that
protects you from having the semaphore hang around in the event that
your program crashes before unlinking it.

Example Solution

// file: pc.cc
#include <semaphore.h>
#include <pthread.h>
#include <cstdio>
#include <cstdlib>
#include <errno.h>

int main(int argc, char *argv[])
{
errno = 0;
sem_t *semaphore = sem_open("/sem5", O_CREAT | O_EXCL, 0, 0);
sem_unlink("/sem5"); //Unlink to ensure semaphore is destroyed if program crashes

if (semaphore == SEM_FAILED) {
int err1 = errno;
fprintf(stderr, "sem_open() failed. errno:%d\n", err1);
if (EEXIST == err1)
fprintf(stderr, "EEXIST : Both O_CREAT and O_EXCL were specified in oflag, but a semaphore with this name already exists. \n");
}

//The semaphore will be closed when the program exits, but can also close it explicitly.
errno = 0;
if(sem_close(semaphore) == -1){
int err2 = errno;
fprintf(stderr, "sem_close() failed. errno:%d\n", err2);
if( EINVAL == err2)
fprintf(stderr, "EINVAL : sem is not a valid semaphore.");

}

return 0;
}


Related Topics



Leave a reply



Submit