display all blocked and pending signals at one time - c

The following program checks if a signal is pending. I use the sigpending function to return blocked (or waiting) signals. The problem is that I don't want this, I would like to display all the blocked and pending signals at some point, how can I do that? What should I change?
code:
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
void catcher(int signum) {
puts("inside catcher!");
if (signum != 0)
perror("signum error");
}
void check_pending(int signum, char * signame) {
sigset_t sigset;
if (sigpending( & sigset) != 0)
perror("sigpending() error");
else if (sigismember( & sigset, signum))
printf("a %s signal is pending\n", signame);
else
printf("no %s signals are pending\n", signame);
}
int main() {
struct sigaction sigact;
sigset_t sigset;
sigemptyset( & sigact.sa_mask);
sigact.sa_flags = 0;
sigact.sa_handler = catcher;
if (sigaction(SIGUSR1, & sigact, NULL) != 0)
perror("sigaction() error");
else {
sigemptyset( & sigset);
sigaddset( & sigset, SIGUSR1);
if (sigprocmask(SIG_SETMASK, & sigset, NULL) != 0)
perror("sigprocmask() error");
else {
puts("SIGUSR1 signals are now blocked");
kill(getpid(), SIGUSR1);
printf("after kill: ");
check_pending(SIGUSR1, "SIGUSR1");
sigemptyset( & sigset);
sigprocmask(SIG_SETMASK, & sigset, NULL);
puts("SIGUSR1 signals are no longer blocked");
check_pending(SIGUSR1, "SIGUSR1");
}
}
}

Use sigignore to dispose the signal. Program below will check pending signals in 1s intervals and display theirs numbers. Terminate with sending SIGTERM.
#define _XOPEN_SOURCE 500
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
int main() {
int i;
sigset_t sigset;
printf("my pid is %d\n", getpid());
sigfillset(&sigset);
sigprocmask(SIG_SETMASK, &sigset, NULL);
while (1) {
sigpending(&sigset);
for (i = 1; i < 32; ++i) {
if (sigismember(&sigset, i)) {
printf("signal %d pending\n", i);
sigignore(i);
if (i == SIGTERM) {
exit(0);
}
}
}
sleep(1);
}
return 0;
}

Related

System Calls in C signals and fork

Hi I've this problem to solve with a functional program in C.
"Write a C program where a process F create a childprocess C.
The childprocess C waits the user to type the password, if is correct sends a signal SIGUSR1 to the father, if after 3 attempts the password is still incorrect it will send a SIGUSR2 signal to the father and terminate; if it receives from the father SIGUSR1 signal must stop viewing the "timeout" message.
His father after 30 seconds (if it has not received any signal from the child) must send the signal SIGUSR1 to the child and end with exit(1); if it receives the SIGUSR1 signal must end with exit(0); if it receives the signal SIGUSR2 must end with exit (2)."
I'm trying to solve it but I'm stuck. This is what I've done:
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <signal.h>
void fatherprocess(int mysignal){
if (mysignal == SIGUSR1) {
printf("ACCESS GRANTED!\n");
exit(0);
}
if (mysignal == SIGUSR2){
printf("ACCESS DISCARDED! More than 3 tentatives!\n");
exit(2);
}
}
void childprocess(int mysignal){
if (mysignal == SIGUSR1) {
printf("TIMEOUT\n");
exit(1);
}
}
int main(int argc, char *argcv[]){
int fatherpid, childpid;
char enteredpassword[], password[] = "test";
int i =0;
unsigned int time_to_sleep = 30;
fatherpid = getpid();
childpid = fork();
if (childpid == 0) {
printf("Child Process waiting for a password\n");
while (1){
if (i < 3) {
printf("Enter Password: ");
scanf("%s", enteredpassword);
if (enteredpassword == password)
signal(SIGUSR1, fatherprocess);
} else {
signal(SIGUSR2, fatherprocess);
exit(1);
}
i++;
}
} else {
printf("Father Process\n");
while(time_to_sleep){
time_to_sleep = sleep(time_to_sleep);
signal(SIGUSR1, childprocess);
}
}
return 0;
}
I've edited my program in this way:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <signal.h>
void fatherprocess(int mysignal, int fatherpid){
if (mysignal == SIGUSR1) {
printf("ACCESS GRANTED!\n");
kill(fatherpid, SIGUSR1);
exit(0);
}
if (mysignal == SIGUSR2){
printf("ACCESS DISCARDED! More than 3 tentatives!\n");
kill(fatherpid, SIGUSR2);
exit(2);
}
}
void childprocess(int mysignal, int childpid){
if (mysignal == SIGUSR1) {
printf("TIMEOUT\n");
kill(childpid, SIGUSR1);
exit(1);
}
}
int main(int argc, char *argcv[]){
int fatherpid, childpid;
char enteredpassword[] = "test", password[] = "test";
int i =0;
unsigned int time_to_sleep = 30;
fatherpid = getpid();
childpid = fork();
if (childpid == 0) {
printf("Child Process waiting for a password\n");
while (1){
if (i < 3) {
printf("Enter Password: ");
scanf("%s", enteredpassword);
if (strcmp(enteredpassword, password) == 0)
fatherprocess(SIGUSR1, fatherpid);
} else {
fatherprocess(SIGUSR2, fatherpid);
exit(1);
}
i++;
}
} else {
printf("Father Process\n");
while(time_to_sleep){
time_to_sleep = sleep(time_to_sleep);
childprocess(SIGUSR1, childpid);
}
}
return 0;
}
Now it works perfectly but I don't know if I've respected the exercise text.
As was mentioned in the comments (by Jonathan Leffler), you need to use the kill() system call (to send the signals) and register a signal handler using a call like sigaction(). I have linked these two calls to online manual pages that provide additional information about them.
Here's some code that demonstrates how these can be used towards achieving your stated goal. You will still need to add/modify the code for things like the prompts you want and the acceptable input string. Please note that I'm not claiming this to be the best way to do it, only that it's an example of how it could be done (it compiled and worked for me):
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
static void get_password(char* buf, int maxbuf)
{
fgets(buf, maxbuf, stdin);
}
static int is_password_correct(char* buf)
{
return buf[0] == 'a';
}
volatile int got_signal = 0;
volatile int child_signal = 0;
static void parent_sig_handler(int signum)
{
if (!got_signal)
{
got_signal = signum;
printf("parent_sig_handler: got sig %d\n", signum);
}
}
static void child_sig_handler(int signum)
{
if (!child_signal)
{
child_signal = signum;
printf("child_sig_handler: got sig %d\n", signum);
}
}
int main()
{
struct sigaction act;
sigfillset(&act.sa_mask);
act.sa_handler = parent_sig_handler;
sigaction(SIGALRM, &act, NULL);
sigaction(SIGUSR1, &act, NULL);
sigaction(SIGUSR2, &act, NULL);
pid_t child_pid = fork();
if (child_pid == -1)
{
perror("error forking");
exit(3);
}
if (child_pid == 0)
{
printf("child running\n");
act.sa_handler = child_sig_handler;
sigaction(SIGUSR1, &act, NULL);
pid_t parent_pid = getppid();
for (int i = 0; i < 3; ++i)
{
char passwd[64];
passwd[0] = '\0';
get_password(passwd, sizeof(passwd));
if (is_password_correct(passwd))
{
kill(parent_pid, SIGUSR1);
exit(0);
}
}
kill(parent_pid, SIGUSR2);
exit(2);
}
printf("parent running\n");
alarm(30); /* sets parent up to receive a SIGALRM signal in 30 seconds */
sigset_t sigmask;
sigemptyset(&sigmask);
while (!got_signal)
{
sigsuspend(&sigmask);
}
switch (got_signal)
{
case SIGALRM:
kill(child_pid, SIGUSR1);
exit(1);
case SIGUSR1:
exit(0);
case SIGUSR2:
exit(2);
default:
exit(3);
}
exit(3);
}

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.

Ping-pong using kill and flags in POSIX

I'm trying to implement interprocess communication by using POSIX signals in C, especially I'm writing Ping-Pong problem. So here's my source code:
#define CHILD 0
#define PARENT 1
int flag[2];
void handler(int sig) {
if (sig == SIGUSR1) {
flag[PARENT] = 1;
} else {
flag[CHILD] = 1;
}
return;
}
void child_process() {
while (1) {
printf("Ping!\n");
kill(getppid(), SIGUSR2);
while (flag[PARENT] == 0) { }
}
return;
}
void parent_process(pid_t t) {
while (1) {
//kill(t, SIGUSR1);
while (flag[CHILD] == 0) { }
printf("Pong!\n");
kill(t, SIGUSR1);
}
return;
}
void setup() {
flag[CHILD] = 0;
flag[PARENT] = 0;
signal(SIGUSR1, handler);
signal(SIGUSR2, handler);
}
int main(int argc, char* argv[]) {
setup();
pid_t t = fork();
if (t == 0) {
child_process();
} else {
parent_process(t);
}
return 0;
}
My program is not working properly, because sometimes I get "Pong!" "Pong!" "Pong!" or "Ping!" "Ping!" output. What's the problem?
And one more question, is my way of handling signals correct? Or there are more advanced ways to do it?
(1) Parent and child do not share the same memory. flag[CHILD] and flag[PARENT] will never know about each other because they are different copies in different processes.
(2) Yes, pretty much everything about your signal handling is wrong for what you are trying to do. You are trying to synchronize the signals so you need to use a mechanism that actually synchronizes them e.g. sigsuspend.
#define _POSIX_C_SOURCE 1
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <sys/types.h>
#include <errno.h>
#define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); } while (0)
void sig_hand(int sig) {}
sigset_t saveMask, blockMask;
void child_process()
{
int x = 0;
while(x < 10)
{
if (sigsuspend(&saveMask) == -1 && errno != EINTR)
errExit("sigsuspend");
printf("Pong %d!\n", ++x);
kill(getppid(), SIGUSR1);
}
return ;
}
void parent_process(pid_t pid)
{
int y = 0;
while (y < 10)
{
printf("Ping %d!\n", ++y);
kill(pid, SIGUSR1);
if (sigsuspend(&saveMask) == -1 && errno != EINTR)
errExit("sigsuspend");
}
return ;
}
int main(int argc, char* argv[])
{
//block SIGUSR1 in parent & child until ready to process it
sigemptyset(&blockMask);
sigaddset(&blockMask, SIGUSR1);
if (sigprocmask(SIG_BLOCK, &blockMask, &saveMask) == -1)
errExit("sigprocmask");
//set up signal handler for parent & child
struct sigaction sa;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
sa.sa_handler = sig_hand;
if (sigaction(SIGUSR1, &sa, NULL) == -1)
errExit("sigaction");
pid_t pid = fork();
if (pid == 0)
child_process();
else
parent_process(pid);
return 0;
}
Although it may not be your problem, remember anytime you are modifying variables asynchronous to program flow, you need to make those variables volatile so that the compilers does not optimize the accesses to them away.
I would think that semaphore.h has much more useful tools (sem_open, sem_post, sem_wait, sem_trywait).
I'd use the sigaction() and pause() functions, along with nanosleep() to rate-limit the activity.
#include <errno.h>
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
enum { MAX_PINGS = 10 };
static sig_atomic_t sig_num;
static void err_exit(const char *fmt, ...)
{
int errnum = errno;
va_list args;
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
if (errnum != 0)
fprintf(stderr, ": (%d) %s", errnum, strerror(errnum));
putc('\n', stderr);
}
static void catcher(int sig)
{
sig_num = sig;
}
static void child_process(void)
{
struct timespec nap = { .tv_sec = 0, .tv_nsec = 100000000 };
while (1)
{
pause();
printf("Pong!\n");
nanosleep(&nap, 0);
kill(getppid(), SIGUSR1);
}
}
static void parent_process(pid_t pid)
{
struct timespec nap = { .tv_sec = 0, .tv_nsec = 100000000 };
for (int pings = 0; pings < MAX_PINGS; pings++)
{
printf("Ping %d!\n", pings);
nanosleep(&nap, 0);
kill(pid, SIGUSR1);
pause();
}
kill(pid, SIGTERM);
}
int main(void)
{
struct sigaction sa;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
sa.sa_handler = catcher;
if (sigaction(SIGUSR1, &sa, NULL) == -1)
err_exit("Failed to set SIGUSR1 handler");
pid_t pid = fork();
if (pid < 0)
err_exit("Failed to fork()");
else if (pid == 0)
child_process();
else
parent_process(pid);
return 0;
}
The variable sig_num is there to quell complaints from the compiler about unused arguments (to the catcher function). The signal catcher is set before the fork(). The child process pauses until a signal arrives; then prints 'Pong!', takes a nap for 1/10 seconds, and then signals the parent process to wake. The parent process prints 'Ping!', takes a nap, signals the child process, and pauses until a signal arrives. It limits the loops to 10 (enough to show it is working), and when it is done, terminates the child before exiting.
Example output
$ ./pingpong
Ping 0!
Pong!
Ping 1!
Pong!
Ping 2!
Pong!
Ping 3!
Pong!
Ping 4!
Pong!
Ping 5!
Pong!
Ping 6!
Pong!
Ping 7!
Pong!
Ping 8!
Pong!
Ping 9!
Pong!
$
Clearly, it would not be hard to print a counter on the 'Pong' values too.

catching all signals in linux

I'm trying to write a process in C/linux that ignores the SIGINT and SIGQUIT signals and exits for the SIGTERM. For the other signals it should write out the signal and the time. I'm having trouble cathing all the signals because i'm familiar only with catching 1 signal. If anyone could help me with this I'd appreciate it very much. Here is my code:
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
int done = 0;
void term(int signum)
{
if (signum == 15)
{
//printf("%d\n",signum);
printf("Received SIGTERM, exiting ... \n");
done = 1;
}
else
{
time_t mytime = time(0);
printf("%d: %s\n", signum, asctime(localtime(&mytime)));
printf("%d\n",signum);
}
}
int main(int argc, char *argv[])
{
struct sigaction action;
memset(&action, 0, sizeof(struct sigaction));
action.sa_handler = term;
sigaction(SIGTERM, &action, NULL);
struct sigaction act;
memset(&act, 0, sizeof(struct sigaction));
act.sa_handler = SIG_IGN;
sigaction(SIGQUIT, &act, NULL);
sigaction(SIGINT, &act, NULL);
int loop = 0;
while(!done)
{
sleep(1);
}
printf("done.\n");
return 0;
}
Here is the easy way
void sig_handler(int signo)
{
if (signo == SIGINT)
printf("received SIGINT\n");
}
int main(void)
{
if (signal(SIGINT, sig_handler) == SIG_ERR)
and so on.
signal() and sighandler() is the least complicated way to do this.
Call signal for each signal that you want to catch. But as some have said earlier you can only catch certain signals. Best to have a way to gracefully shut the program down.

Some wrong about sigsetjmp

I am reading the APUE, Chapter 10. Here is my code.
#include "apue.h"
#include <unistd.h>
#include <setjmp.h>
#include <time.h>
#include <errno.h>
static void sig_usr1(int), sig_alrm(int);
static sigjmp_buf jmpbuf;
static volatile sig_atomic_t canjmp;
int
main(void)
{
if(signal(SIGUSR1, sig_usr1) == SIG_ERR)
err_sys("signal(SIGUSR1) error");
if(signal(SIGALRM, sig_alrm) == SIG_ERR)
err_sys("signal(SIGALRM) error");
//print signal.
pr_mask("Starting main: ");
if(sigsetjmp(jmpbuf, 1)) {
pr_mask("End main: ");
exit(0);
}
canjmp = 1;
for(;;)
pause();
}
static void
sig_usr1(int signo)
{
time_t starttime;
if(canjmp == 0) {
return;
}
pr_mask("starting sig_usr1: ");
alarm(3);
starttime = time(NULL);
for(;;)
if(time(NULL) > starttime + 5)
break;
pr_mask("finishing sig_usr1: ");
canjmp = 0;
siglongjmp(jmpbuf, 1);
}
static void
sig_alrm(int signo)
{
pr_mask("in sig_arlm: ");
}
void
pr_mask(const char *str)
{
sigset_t sigset;
int errno_save;
errno_save = errno; /* we can be called by signal handlers */
if (sigprocmask(0, NULL, &sigset) < 0)
err_sys("sigprocmask error");
printf("%s", str);
if (sigismember(&sigset, SIGUSR1)) printf("SIGUSR1 ");
if (sigismember(&sigset, SIGALRM)) printf("SIGALRM ");
/* remaining signals can go here */
printf("\n");
errno = errno_save;
}
I thought the output would be like this:
Starting main:
starting sig_usr1: SIGUSR1
in sig_alrm: SIGUSR1 SIGALRM
finishing sig_usr1: SIGUSR1
End main:
but it seems something wrong, this is my output in fact:
Starting main:
starting sig_usr1:
in sig_alrm:
finishing sig_usr1:
End main:
that is no signals. Please help me.
I think the trouble is probably that you are using signal() and not sigaction() to set the signal handling. And signal() does not mask any other signals - so there are no signals to show as being blocked. I modified your code as shown below, to use signal() and sigaction() depending on whether there are any arguments or not.
#include <signal.h>
#include <unistd.h>
#include <setjmp.h>
#include <time.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
typedef void (*Handler)(int);
static void sig_usr1(int), sig_alrm(int);
static sigjmp_buf jmpbuf;
static volatile sig_atomic_t canjmp;
static void pr_mask(const char *str);
static void err_sys(const char *str)
{
int errnum = errno;
fprintf(stderr, "%s (%d: %s)\n", str, errnum, strerror(errnum));
exit(1);
}
static void set_sigaction(int signum, Handler handler)
{
struct sigaction nact;
nact.sa_handler = handler;
sigfillset(&nact.sa_mask);
//sigemptyset(&nact.sa_mask);
nact.sa_flags = 0;
if (sigaction(signum, &nact, 0) != 0)
err_sys("Failed to set signal handling");
}
int
main(int argc, char **argv)
{
printf("PID = %u\n", (unsigned)getpid());
if (argc > 1)
{
if (signal(SIGUSR1, sig_usr1) == SIG_ERR)
err_sys("signal(SIGUSR1) error");
if (signal(SIGALRM, sig_alrm) == SIG_ERR)
err_sys("signal(SIGALRM) error");
}
else
{
set_sigaction(SIGUSR1, sig_usr1);
set_sigaction(SIGALRM, sig_alrm);
}
//print signal.
pr_mask("Starting main: ");
if (sigsetjmp(jmpbuf, 1)) {
pr_mask("End main: ");
exit(0);
}
canjmp = 1;
for (;;)
pause();
}
static void
sig_usr1(int signo)
{
time_t starttime;
if (canjmp == 0) {
return;
}
pr_mask("starting sig_usr1: ");
alarm(3);
starttime = time(NULL);
for (;;)
if (time(NULL) > starttime + 5)
break;
pr_mask("finishing sig_usr1: ");
canjmp = 0;
siglongjmp(jmpbuf, 1);
}
static void
sig_alrm(int signo)
{
pr_mask("in sig_arlm: ");
}
void
pr_mask(const char *str)
{
sigset_t sigset;
int errno_save;
errno_save = errno; /* we can be called by signal handlers */
if (sigprocmask(0, NULL, &sigset) < 0)
err_sys("sigprocmask error");
printf("%s", str);
if (sigismember(&sigset, SIGUSR1)) printf("SIGUSR1 ");
if (sigismember(&sigset, SIGALRM)) printf("SIGALRM ");
/* remaining signals can go here */
printf("\n");
errno = errno_save;
}
Running on MacOS X 10.7.2 with current XCode (4.2?), I get (for example):
$ ./sigtest
PID = 11066
Starting main:
starting sig_usr1: SIGUSR1 SIGALRM
finishing sig_usr1: SIGUSR1 SIGALRM
in sig_arlm: SIGUSR1 SIGALRM
End main:
$ ./sigtest 1
PID = 11067
Starting main:
starting sig_usr1: SIGUSR1
in sig_arlm: SIGUSR1 SIGALRM
finishing sig_usr1: SIGUSR1
End main:
$

Resources