sigaction Definition
Name:
- sigaction, rt_sigaction - examine and change a signal action
Synopsis:
- #include <signal.h>
- int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
DESCRIPTION
- The sigaction() system call is used to change the action taken by a process on receipt of a specific signal.
- signum specifies the signal and can be any valid signal except SIGKILL and SIGSTOP.
- If act is non-NULL, the new action for signal signum is installed from act.
- If oldact is non-NULL, the previous action is saved in oldact.
- The sigaction structure is defined as something like:
void (*sa_handler)(int);
void (*sa_sigaction)(int, siginfo_t *, void *);
sigset_t sa_mask;
int sa_flags;
void (*sa_restorer)(void);
};
Note: On some architectures a union is involved: do not assign to both sa_handler and sa_sigaction.
- The sa_restorer field is not intended for application use.
- If SA_SIGINFO is specified in sa_flags, then sa_sigaction (instead of sa_handler)
sa_mask specifies a mask of signals which should be blocked - The siginfo_t data type is a structure with the following fields:
int si_signo; /* Signal number */
int si_errno; /* An errno value */
int si_code; /* Signal code */
int si_trapno; /* Trap number that caused
hardware-generated signal
(unused on most architectures) */
pid_t si_pid; /* Sending process ID */
uid_t si_uid; /* Real user ID of sending process */
int si_status; /* Exit value or signal */
clock_t si_utime; /* User time consumed */
clock_t si_stime; /* System time consumed */
sigval_t si_value; /* Signal value */
int si_int; /* POSIX.1b signal */
void *si_ptr; /* POSIX.1b signal */
int si_overrun; /* Timer overrun count;
POSIX.1b timers */
int si_timerid; /* Timer ID; POSIX.1b timers */
void *si_addr; /* Memory location which caused fault */
long si_band; /* Band event (was int in
glibc 2.3.2 and earlier) */
int si_fd; /* File descriptor */
short si_addr_lsb; /* Least significant bit of address
(since Linux 2.6.32) */
void *si_lower; /* Lower bound when address violation
occurred (since Linux 3.19) */
void *si_upper; /* Upper bound when address violation
occurred (since Linux 3.19) */
int si_pkey; /* Protection key on PTE that caused
fault (since Linux 4.6) */
void *si_call_addr; /* Address of system call instruction
(since Linux 3.5) */
int si_syscall; /* Number of attempted system call
(since Linux 3.5) */
unsigned int si_arch; /* Architecture of attempted system call
(since Linux 3.5) */
}
- si_signo, si_errno and si_code are defined for all signals.
- Signals sent with kill(2) and sigqueue(3) fill in si_pid and si_uid.
- In addition, signals sent with sigqueue(3) fill in si_int and si_ptr with the values specified by the sender of the signal
The si_code field:
- The si_code field inside the siginfo_t argument that is passed to a SA_SIGINFO signal handler is a value (not a bit mask) indicating why this signal was sent.
- The following values can be placed in si_code for a SIGILL signal:
ILL_ILLOPC
Illegal opcode.
ILL_ILLOPN
Illegal operand.
ILL_ILLADR
Illegal addressing mode.
ILL_ILLTRP
Illegal trap.
ILL_PRVOPC
Privileged opcode.
ILL_PRVREG
Privileged register.
ILL_COPROC
Coprocessor error.
Illegal opcode.
ILL_ILLOPN
Illegal operand.
ILL_ILLADR
Illegal addressing mode.
ILL_ILLTRP
Illegal trap.
ILL_PRVOPC
Privileged opcode.
ILL_PRVREG
Privileged register.
ILL_COPROC
Coprocessor error.
RETURN VALUE
- sigaction() returns 0 on success; on error, -1 is returned, and set errno.
ERRORS
- EFAULT act or oldact points to memory which is not a valid part of the process address space.
sigqueue
Name
- sigqueue - queue a signal and data to a process
SYNOPSIS
- #include <signal.h>
- int sigqueue(pid_t pid, int sig, const union sigval value);
DESCRIPTION
- sigqueue() sends the signal specified in sig to the process whose PID is given in pid.
- The value argument is used to specify an accompanying item of data (either an integer or a pointer value) to be sent with the signal, and has the following type:
union sigval {
int sival_int;
void *sival_ptr;
};
int sival_int;
void *sival_ptr;
};
- If the receiving process has installed a handler for this signal using the SA_SIGINFO flag to sigaction(2), then it can obtain this data via the si_value field of the siginfo_t structure
RETURN VALUE
- On success, sigqueue() returns 0, Otherwise, -1 is returned and set errno .
Program
/* Send an signal with an argument (integer value) by Velraj.K
* Check : http://velrajcoding.blogspot.in
*/
#include <stdio.h>
#include <stdlib.h> // For exit()
#include <string.h> // For memset()
#include <unistd.h> // For fork() & sleep()
#include <sys/wait.h> // For sig_atomic_t, siginfo_t, sigaction, SA_SIGINFO, SIGUSR1, SIGUSR2, sigqueue(), wait()
#include <assert.h> // For assert()
static volatile sig_atomic_t got_value = 0;
void sig_handler(int sig, siginfo_t *info, void *x)
{
pid_t pid = 0;
pid = getpid();
/* info->si_value.sival_int contains the integer value receive from sender */
switch (info->si_value.sival_int) {
case 1:
printf("Vel Child:%d, received Signal with arg value as 1 sig num = %d SIG_USR1:%d SIG_USR2:%d \n", pid, sig, SIGUSR1, SIGUSR2);
break;
case 2:
printf("Vel Child:%d, received Signal with arg value as 2 sig num = %d \n", pid, sig);
break;
default:
printf("Invalid value \n");
break;
}
++got_value;
return;
}
int main()
{
struct sigaction act = {0};
int ret;
int status = 0;
pid_t pid = -1;
union sigval send_arg = {0};
act.sa_flags = SA_SIGINFO;
act.sa_sigaction = sig_handler;
/* Install hangler for singal */
ret = sigaction(SIGUSR1, &act, NULL);
assert(ret == 0);
ret = sigaction(SIGUSR2, &act, NULL);
assert(ret == 0);
/* Create child process & send the signal from parent to Child */
pid = fork();
/*
* On success, parent process get child PID,
* Child process get pid as 0
*/
if (-1 == pid) {
exit(1);
} else if (0 == pid) {
/* Child process */
while (2 != got_value) {
sleep(1);
}
exit(0);
} else {
/* Parent process */
/* Send signal along with value 1 */
send_arg.sival_int = 1;
printf("Vel Parent:%d send SIGUSR2 with arg value as 1 to the Child:%d \n", getpid(), pid);
sigqueue(pid, SIGUSR2, send_arg);
/* Send signal along with value 2 */
send_arg.sival_int = 2;
printf("Vel Parent:%d send SIGUSR1 with arg value as 2 to the Child:%d \n", getpid(), pid);
sigqueue(pid, SIGUSR1, send_arg);
wait(&status);
printf("Vel Parent:%d --> Status return by Child:%d \n", getpid(), status);
}
return 0;
}
Output:
Vel Parent:10474 send SIGUSR2 with arg value as 1 to the Child:10475Vel Parent:10474 send SIGUSR1 with arg value as 2 to the Child:10475
Vel Child:10475, received Signal with arg value as 1 sig num = 12 SIG_USR1:10 SIG_USR2:12
Vel Child:10475, received Signal with arg value as 2 sig num = 10
Vel Parent:10474 --> Status return by Child:0
Reference:
- http://man7.org/linux/man-pages/man2/sigaction.2.html
- http://man7.org/linux/man-pages/man3/sigqueue.3.html