Sunday, 6 October 2013

[Operating Systems #3] Sigaction API C code examples

Please refer previous posts for understanding the concepts related to asynchronous signals and useful APIs (including signal API and sigaction API)

Example-1
=========
/*
 *  Child process auto clean-up using sigaction API.
 * If child process is done with its task, then it will be pushed to defunc state.
 * Parent process has to instruct the Kernel Process Manager to destroy the child process using wait function. Instead of blocking parent process until child process termination, we use sigaction API.
 * Using sigaction(), we register a function call back sighandle(), this function will be called when child process has done with its task. In the mean time, parent process can do its own task without dependent on child process.
*/

#include<signal.h>
#include<stdio.h>
#include<string.h>

void sighandler (int signum)
{
printf("Sighandler: I am in sighandler\n");
}

void main()
{
struct sigaction act;
pid_t cpid;

memset(&act, 0, sizeof(act));

act.sa_handler = sighandler;
act.sa_flags = SA_NOCLDWAIT; /* Setting up auto clean-up */

if (sigaction(SIGCHLD, &act, NULL) < 0)
printf("Sigaction reg is failed\n");

cpid = fork();

if (cpid == 0) {
printf("Child: I am in child process\n");
sleep(8);
printf("Child: Done with its task\n");
}
else {
printf("Parent: I am in parent process\n");
while (1) {
printf("main: in loop\n");
sleep(2);
}
}
}

Output:
========
Parent: I am in parent process
main: in loop
Child: I am in child process
main: in loop
main: in loop
main: in loop
Child: Done with its task
Sighandler: I am in sighandler
main: in loop
main: in loop
main: in loop
main: in loop
main: in loop
^C

Observation:
==============
When child and parent process are executing.
rrajk      3044  2067  0 08:56 pts/0    00:00:00 ./sigaction_child
rrajk      3045  3044  0 08:56 pts/0    00:00:00 ./sigaction_child

Once child terminated, sighandler will be called.
rrajk      3044  2067  0 08:56 pts/0    00:00:00 ./sigaction_child

Since we set flag SA_NOCLDWAIT, the child process is destroyed once its done its task.
Otherwise it would be pushed to defunc state.




Example-2
=========
/*
 * Blocking a signal of type 'Y' if another signal of type 'X' is in its handler.
 * Once signal X is completed its task, signal Y's handler is invoked.
 * Use sigaddset() with sigaction() API
*/

#include<signal.h>
#include<stdio.h>
#include<string.h>

void sighandler (int signum)
{
printf("Sighandler: I am in sighandler before sleep\n");
sleep(3);
printf("Sighandler: I am in sighandler after sleep\n");
}

void main()
{
struct sigaction act;
sigset_t sigmask;
int rc;

memset(&act, 0, sizeof(act));
rc = sigemptyset(&sigmask);
printf("sigemptyset return value: %d\n", rc);

rc = sigaddset(&sigmask, SIGQUIT); /* Block this signal if the process is in its handler */
rc = sigaddset(&sigmask, SIGTERM); /* same above */
printf("sigaddset return value: %d\n", rc);

act.sa_handler = sighandler;
act.sa_mask = sigmask;

if (sigaction(SIGINT, &act, NULL) < 0)
printf("Sigaction reg is failed\n");

while (1) {
printf("main: in loop\n");
sleep(2);
}
}

Output:
========
sigemptyset return value: 0
sigaddset return value: 0
main: in loop
main: in loop
main: in loop
^CSighandler: I am in sighandler before sleep
^\Sighandler: I am in sighandler after sleep
Quit (core dumped)

Observation:
==============
If CTRL+C is generated and this signal is in its handler. Now, CTRL+\ (SIGQUIT) is gernerated then it will be blocked until
CTRL+C handler completes its execution.
Once CTRL+C handler done with its task then CTRL+\ handler will be executed.


Example-3
=========
/*
 * sa_flags member in sigaction structure usage.
*/

#include<signal.h>
#include<stdio.h>
#include<string.h>

void sighandler (int signum)
{
printf("Sighandler: I am in sighandler\n");
sleep(3);
}

void main()
{
struct sigaction act;

memset(&act, 0, sizeof(act));

act.sa_handler = sighandler;
act.sa_flags = SA_NODEFER; /* Do not prevent the signal from being received from within its own sighandler */

if (sigaction(SIGINT, &act, NULL) < 0)
printf("Sigaction reg is failed\n");

while (1) {
printf("main: in loop\n");
sleep(2);
}
}

/*Output:
========
main: in loop
main: in loop
^CSighandler: I am in sighandler
^CSighandler: I am in sighandler
^CSighandler: I am in sighandler
^CSighandler: I am in sighandler
main: in loop
main: in loop
main: in loop
main: in loop
main: in loop
main: in loop
^CSighandler: I am in sighandler
^CSighandler: I am in sighandler
main: in loop
User defined signal 1

Observation:
==============
SA_NODEFER flag usage. Since we set the flag NODEFER, the signals are delivered to registered process without any delay once they are generated. So, we saw "I am in sighandler" for 4 times (I pressed CTRL+C 4 times).
If we remove this flag then the behavior is different. Please refer post #2 sigaction section.
Try at your end by commenting SA_NODEFER line and observe the output.



No comments:

Post a Comment

You might also like

Related Posts Plugin for WordPress, Blogger...