How to install a signal handler names sig_handler - c

Hi i've done this code but there are somethings i need to add like.
ignore signal SIGINT
restore the signal handler for SIGINT to the default one
catch signal SIGINT and prints out the numerical value of the signal
so far this is the coding i have
void sig_handler(int signo)
{
// body of signal handler
}
int main()
{
struct sigaction act;
act.sa_flags = 0;
act.sa_handler = sig_handler;
sigfillset( & (act.sa_mask) );
if (sigaction(sig, &act, NULL) != 0)
{
perror("sigaction"); exit(1);
}
}

Something like this will get you started.
#include <stdio.h>
#include <signal.h>
void handle_signal(int signum)
{
printf("\nRecived signal: %d\n", signum);
switch(signum)
{
case SIGINT:
printf("I won't respond to ctrl-c!\n");
//restore to default
signal(SIGINT, SIG_DFL);
break;
case SIGWINCH:
//windows size change
break;
case SIGCONT:
//continue process 'fg' in terminal
break;
case SIGTSTP:
//ctrl-z
break;
default:
//others
break;
}
}
void listen_to_signals(void)
{
int i;
i = 0;
while (i < 32)
{
if (i != SIGKILL && i != SIGSTOP && i != SIGCHLD && i != SIGCONT &&
i != SIGURG && i != SIGIO)
signal(i, &handle_signal);
i++;
}
}
int main()
{
listen_to_signals();
while(1)
{}
}
Note, I'm listening to all signals I can: there are some signals that I can't listen to (like kill).
Note: use 'kill -9 pidof your_program' to stop it
Note: the first time SIGINT will be ignored, but the second time, it won't (because I'm restoring it to its default behavior)

Related

determine what secret handshake causes them to print the given lines ONE TIME ONLY

So I need to find what causes this program to print out "I'm unlocked!" But when I run this algorithm, it prints out nothing.
I tried removing lines of code or adding sleep but no matter what I do it just prints out blank.
I am expected to print "I'm unlocked!"
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
volatile int locked, t, c;
static void handler(int signo);
int main(int argc, char * argv[])
{
locked = 1;
t = c = 0;
char * knock = getenv("KNOCK");
if(knock == NULL || strcmp(knock, "KNOCK"))
{
return 1;
}
if(signal(SIGUSR1, handler) == SIG_ERR ||
signal(SIGUSR2, handler) == SIG_ERR ||
signal(SIGALRM, handler) == SIG_ERR)
{
fprintf(stderr, "%s: cannot register signal handlers\n", argv[0]);
return 2;
}
while(locked)
{
pause();
}
puts("I'm unlocked!");
return 0;
}
static void handler(int signo)
{
switch(signo)
{
case SIGUSR1:
if(c == 2)
{
t = alarm(3);
}
break;
case SIGUSR2:
c++;
if(t == 1)
{
locked = 0;
}
break;
case SIGALRM:
t = 0;
break;
}
}
The pause() function suspends the calling thread and returns when a signal that has a registered handler is invoked.
The loop then terminates when pause() returns and the locked == 0.
So the following signal sequence and timing will unlock:
SIGUSR2 // c = 1
SIGUSR2 // c = 2
SIGUSR1 // t = 0 (no scheduled alarm)
Delay two seconds
SIGUSR1 // t = 1 (alarm seconds remaining)
SIGUSR2 // locked = 0 (because t == 1)
The signals can be issued from a separate thread or process using the kill() function or from a shell script using the kill command.

Two signals in the same main

I want to use two signals in the same main. So I made two handlers etc. That's my code:
volatile sig_atomic_t go_on = 0;
volatile sig_atomic_t execute = 0;
void sig_syn(int sig_no)
{
go_on = 1;
}
void exe_handler(int sig_no)
{
execute = 1;
}
struct sigaction action;
sigset_t mask;
struct sigaction e_action;
sigset_t e_mask;
sigfillset (&mask);
action.sa_handler = sig_syn;
action.sa_mask = mask;
action.sa_flags = 0;
sigaction (SIGRTMIN, &action, NULL);
sigfillset (&e_mask);
e_action.sa_handler = exe_handler;
e_action.sa_mask = e_mask;
e_action.sa_flags = 0;
sigaction (SIGRTMIN, &e_action, NULL);
while(go_on == 0){}
go_on = 0;
.
.
.
while(execute == 0){}
execute = 0;
.
.
.
Is it correct that i use all these two times? The reason I ask is because my program doesn't run but no errors appear... Any help? Thanks in advance!
First of all, if your program doesn't run try out putting some debugging, gdb would be better, but printfs can do the job.
A Unix program can receive a lot of signals, checkout "man signal" to the usage and "man 7 signal" to all signals.
I'written and tested the following code.
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
void
termination_handler (int signum)
{
printf("Signal %d\n",signum);
exit(0);
}
int signal1 = 0;
void
usr_signal1(int signum)
{
printf("Signal 1 received\n");
signal1 = 1;
}
int signal2 = 0;
void
usr_signal2(int signum)
{
printf("Signal 2 received\n");
signal2 = 1;
}
int
main (void)
{
printf("My pid is : %d\n",getpid());
if (signal (SIGTERM, termination_handler) == SIG_IGN)
signal (SIGTERM, SIG_IGN);
if (signal (SIGUSR1, usr_signal1) == SIG_IGN)
signal(SIGUSR1, SIG_IGN);
if (signal (SIGUSR2, usr_signal2) == SIG_IGN)
signal(SIGUSR2, SIG_IGN);
printf("Main has started\n");
while(0 == signal1) { sleep(1); };
printf("Main moved to stade 1 \n");
while(0 == signal2) { sleep(1); };
printf("Main moved to stade 2 \n");
printf("Main is done ! \n");
return 0;
}
After compiling and running, it will print it's pid and keep waiting signals SIGUSR1 and SIGUSR2.
$ ./main
My pid is : 6365
Main has started
Signal 1 received
Main moved to stade 1
Signal 2 received
Main moved to stade 2
Main is done !
Sending the kills with
kill -10 6365
kill -12 6365
works.

SIGTERM to all children processes but not parent

I have a C program that operates by responding to signals. Some signals cause the parent to fork. This allows other processing while the parent continues to respond to signals.
When the parent is sent a SIGTERM, I want the forked children to receive a SIGTERM as well. It isn't critical that the children finish handling the SIGTERM before the parent exits.
However, with the below code, the children do not receive a SIGTERM when I call kill(0, SIGTERM) from the parent. From the kill manpage, it looks like all of the children should get this SIGTERM.
I have a signal handler setup for the parent.
static volatile sig_atomic_t done = 0;
const int handled_signals[] = {SIGINT, SIGTERM, 0};
static void set_flag(int signum) {
switch (signum) {
/* Intentionally exclude SIGQUIT/SIGABRT/etc. as we want to exit
* without cleaning up to help with debugging */
case SIGTERM:
case SIGINT:
done = 1;
break;
default:
/* Should be unreachable, but just in case */
if (signal(signum, SIG_DFL) != SIG_ERR) {
raise(signum);
}
}
}
static int setup_handlers() {
struct sigaction sa;
sigset_t block_all;
int i;
/* Block all other signals while handling a signal. This is okay as
* our handler is very brief */
sigfillset(&block_all);
sa.sa_mask = block_all;
sa.sa_handler = set_flag;
for (i = 0; handled_signals[i] != 0; i++) {
if (sigaction(handled_signals[i], &sa, NULL)) {
err_log("Unable to set sigaction");
return 1;
}
}
/* Ignore SIGCHLD as we don't keep track of child success */
sa.sa_handler = SIG_IGN;
if (sigaction(SIGCHLD, &sa, NULL)) {
err_log("Unable to ignore SIGCHLD");
return 1;
}
return 0;
}
int main() {
int i;
sigset_t block_mask, orig_mask;
setup_handlers();
/* Block all of our handled signals as we will be using
* sigsuspend in the loop below */
sigemptyset(&block_mask);
for (i = 0; handled_signals[i] != 0; i++) {
sigaddset(&block_mask, handled_signals[i]);
}
if (sigprocmask(SIG_BLOCK, &block_mask, &orig_mask)) {
err_log("Error blocking signals");
}
while (!done) {
if (sigsuspend(&orig_mask) && errno != EINTR) {
err_log("sigsuspend");
}
}
/* Kill all children */
if (kill(0, SIGTERM)) {
err_log("kill(0, SIGTERM))");
}
}
After getting a signal that requires a fork, I do the following
static int unregister_handlers() {
struct sigaction sa;
int i;
sa.sa_handler = SIG_DFL;
for (i = 0; handled_signals[i] != 0; i++) {
if (sigaction(handled_signals[i], &sa, NULL)) {
err_log("sigaction unregister");
return 1;
}
}
if (sigaction(SIGCHLD, &sa, NULL)) {
err_log("sigaction SIGCHLD unregister");
return 1;
}
return 0;
}
void do_fork() {
switch(fork()) {
/* Error */
case -1:
err_log("fork");
break;
/* Child */
case 0:
if (unregister_handlers()) {
_exit(1);
}
do_fork_stuff();
_exit(0);
break;
/* Parent */
default:
break;
}
}
In do_fork_stuff, the child sleeps for 30 seconds. I then call kill(0, SIGTERM) from the parent. The children do not terminate.
What's the reason the children aren't getting the SIGTERM?
Ah, a little help from /proc/[PID]/status solved this.
$ cat /proc/31171/status
Name: myprog
SigQ: 2/16382
SigPnd: 0000000000000000
ShdPnd: 0000000000000000
SigBlk: 0000000000004203
SigIgn: 0000000000000000
SigCgt: 0000000180000000
The blocked signals (SigBlk) were the issue here. While the handlers were unregistered, the children were blocking SIGTERM. Removing the blocked signals resolved the issue.

Asynchronous signals from children to parent and sigaction()

Important pre-knowledge: I have two children that were forked by the original process. The children simply send one of the two user-defined signals (SIGUSR1 or SIGUSR2) to the parent.
The code is constructed as follows:
if (pid == 0 || second_child == 0) {
/* Just some pseudocode for basic logic */
while (1) {
sleep(2);
kill(parent_pid, SIGUSR1) or kill(parent_pid, SIGUSR2);
}
} else {
while (1) {
struct sigaction psa;
psa.sa_handler = sigHandler;
/* three signals that need to be handled */
sigaction(SIGUSR1, &psa, NULL);
sigaction(SIGUSR2, &psa, NULL);
sigaction(SIGINT, &psa, NULL);
pause();
}
}
sigHandler method:
void sigHandler (int sigNum) {
switch(sigNum) {
case SIGUSR1:
//print something using write()
break;
case SIGUSR2:
//print something using write()
break;
default:
exit(0);
}
}
The calls to sigHandler() do not occur as they should. The print statements that occur in sigHandler() eventually just stop and there is no output. I believe the problem deals with a signal being sent to the parent while the sigHandler is being executed, but I am not certain.

Is there a way to sigaction() to a signal handler with multiple parameters?

I am using sigaction() to perform an action every time SIGINT is received. All tutorials I have seen use this prototype as a signal handler
void sig_handler(int sig);
Is there a way somehow to make this to take more parameters so it suits my needs? So for example
void sig_handler(char* surname, int age);
This is my code:
void sig_handler(int sig) {
printf("SIGINT(%d) received\n", sig);
}
int main( ){
struct sigaction act;
act.sa_handler=sig_handler;
sigaction(SIGINT, &act, NULL);
while(1){};
return 0 ;
}
Not directly, but you could set a global variable that tells your sig_handler() what to do.
int ACTION = 0;
void sig_handler(int sig) {
if (sig == SIGINT) {
switch (ACTION) {
case 0: other_function(char* surname, int age);
break;
// more cases
default:
;
}
} else if ( .... // more signals
}
}
int main( ){
struct sigaction act;
act.sa_handler=sig_handler;
sigaction(SIGINT, &act, NULL);
while(1){};
return 0 ;
}
You can't do this with signals. How would these parameters be supplied and delivered? A signal is just a predefined numeric code that causes the process to execute the handler asynchronously, by interrupting the main flow.
You can, however, use a Unix socket, a pipe, or a fifo file for this.

Resources