C program to make process sleep by using sem_wait and wake it up by doing sem_post in SIGTERM signal handler

C program to make a process sleep by using "sem_wait". The Process would wake up by doing sem_post in SIGTERM signal handler, to which the process has registered to.


Program:
neelkanth_surekha#cat sem.c 
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <semaphore.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <pthread.h>
#include <time.h>
#include <string.h>
#include <signal.h>

/* define macro printf for printf , where in printf takes same arguments as printf and 
 *  also prints timestamp  */
#define LOG_INIT()          time_t ltime; /* calendar time */ \
    char *ptr;\

#define printf(...)      ltime = time(NULL); /* get current cal time */ \
                                 ptr = asctime( localtime(&ltime));\
ptr[strlen(ptr)-1] = '\0';\
printf("%s: ", ptr); \
printf(__VA_ARGS__); printf("\n");

#define SEM_NAME "neel_semaphore"
#define SEM_PERMS (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP)
#define INITIAL_VALUE  0

void sig_handler(int signo)
{
    LOG_INIT();
    sem_t *semaphore = sem_open(SEM_NAME, O_CREAT , SEM_PERMS,
            0);
    int sem_value;

    printf("INSIDE signal handler\n");

    if (semaphore == SEM_FAILED) {
        printf("sem_open(3) error");
        exit(EXIT_FAILURE);
    }

    if (signo == SIGTERM)
    {
        if (!sem_getvalue(semaphore, &sem_value)) {
            printf("PID %d semaphore value before sem_post: %d\n", getpid(), sem_value);
        }

        if (sem_value == 0) {
            /* sem_post() increments (unlocks) the semaphore pointed to by sem.  If
             * the semaphore's value consequently becomes greater than zero, then
             * another process or thread blocked in a sem_wait call will be woken
             * up and proceed to lock the semaphore. */
            if (sem_post(semaphore) < 0) {
                printf("sem_post(3) error on child");
            }
            printf("Sem_post done. i.e. semaphore count is incremented to 1\n");
        }

        if (!sem_getvalue(semaphore, &sem_value)) {
            printf("PID %d semaphore value after sem_post: %d\n", getpid(), sem_value);
        }

        if (sem_close(semaphore) < 0) {
            printf("sem_close(3) failed");
        }
    }

    printf("EXIT signal handler\n");
    return;
}


void main()
{
    LOG_INIT();
    /* Register this process for SIGTERM signal handler so that 
     * the semaphore count will be incremented to 1 when the process
     * receives this signal
     */
    if (signal(SIGTERM, sig_handler) == SIG_ERR )
    {
        printf("can't catch SIGTERM\n");
    }

    int sem_value = 0;

    /* We initialize the semaphore counter to 0 (INITIAL_VALUE) 
     * If O_CREAT  is specified in oflag, then the semaphore is created 
     * if it does not already exist.
     * If both O_CREAT and O_EXCL are specified in oflag, then an error 
     * is returned if a semaphore
     * with the given name already exists.
     */
    /* sem_open() creates a new POSIX semaphore or opens an existing
     * semaphore.  The semaphore is identified by name. 
     */
    sem_t *semaphore = sem_open(SEM_NAME, O_CREAT , SEM_PERMS, INITIAL_VALUE);
    if (semaphore == SEM_FAILED) {
        printf("sem_open(3) error");
        exit(EXIT_FAILURE);
    }

    printf("PID %ld trying to acquire semaphore", (long) getpid());

    if (!sem_getvalue(semaphore, &sem_value)) {
        printf("PID %d semaphore value: %d", getpid(), sem_value);
    }

    
/* check whether the semaphore is available of not.  */
    if (sem_value ==  0)
    {
        printf("PID %d: Semaphore name: %s\nSleep here till the semaphore count"
                "is increased to 1 \n", getpid(), SEM_NAME);
    }

    
/* sem_wait() decrements (locks) the semaphore pointed to by sem.  If
     * the semaphore's value is greater than zero, then the decrement
     * proceeds, and the function returns, immediately.  If the semaphore
     * currently has the value zero, then the call blocks until either it
     * becomes possible to perform the decrement (i.e., the semaphore value
     * rises above zero), or a signal handler interrupts the call.*/
    /* If the semaphore value is 0, wait here till the value increase to 
     * greater than 0 */
    if (sem_wait(semaphore) < 0) {
        printf("sem_wait(3) failed on child");
        exit(EXIT_FAILURE);
    }

    printf("PID %ld release semaphore\n", (long) getpid());

    sem_unlink(SEM_NAME);

    return;
}


Output:
Terminal 1: Start the process
neelkanth_surekha#./a.out 
Wed Dec 27 09:11:29 2017: PID 6330 trying to acquire semaphore
Wed Dec 27 09:11:29 2017: PID 6330 semaphore value: 0
Wed Dec 27 09:11:29 2017: PID 6330: Semaphore name: neel_semaphore
Sleep here till the semaphore countis increased to 1 

Wed Dec 27 09:11:42 2017: INSIDE signal handler

Wed Dec 27 09:11:42 2017: PID 6330 semaphore value before sem_post: 0

Wed Dec 27 09:11:42 2017: Sem_post done. i.e. semaphore count is incremented to 1

Wed Dec 27 09:11:42 2017: PID 6330 semaphore value after sem_post: 1

Wed Dec 27 09:11:42 2017: EXIT signal handler

Wed Dec 27 09:11:42 2017: PID 6330 release semaphore

Terminal 2: Give Kill -15 to process
neelkanth_surekha#ps -elf | grep a.out
0 S neelkan+  6330  5227  0  80   0 -  1632 futex_ 09:11 pts/1    00:00:00 ./a.out
0 S neelkan+  6333  6079  0  80   0 -  3556 pipe_w 09:11 pts/19   00:00:00 grep --color=auto a.out