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(<ime));\
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