How do I use the SIGALRM correctly? - c

I'm made this code, and I have to use the alarm signal (SIGALRM) to make the program print the message “I am alive.” every 3 seconds.
But it doesn't work, it sends the message "I'm Alive" only when I press CTR-C, I'm guessing
I didn't put the SIGALRM function in the right place, can you help me?
#include <stdlib.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
unsigned Count = 0; //Counts the number of times it receives the signal SIGINT.
void mypause(int sign); //prototype of the function my pause.
void mypause(int sign) {
signal(SIGALRM, mypause); //Set alarm clock for 3 seconds.
alarm(3);
printf("I'm Alive");
signal(SIGINT, mypause);
switch (sign) {
case SIGINT:
printf("\nPressed CTR-C\n");
printf("I'm running, waiting for a sign\n");
Count++;
break;
case SIGQUIT:
printf("\nPressed CTR-\\n");
printf("You pressed CTR-C %d times", Conta);
exit(0); //Exit program.
break;
}
}
int main() {
signal(SIGALRM, mypause);
signal(SIGINT, mypause);
signal(SIGQUIT, mypause);
printf("\nI'm running waiting for a signal\n");
while (1) {}
return (0);
}

Maybe add alarm(3) in your main() ?

Related

Use sigwait to block a specific signal without blocking SIGINT

I have a program that runs a loop, each time at the end of the loop, the process should sleep for some seconds(the number of seconds is not constant and is calculated at each loop) or until the process receives SIGINT, I used alarm() and sigwait() to do this but it's blocking the ctrl+c signal(i.e SIGINT) which I don't want, I want SIGINT to be received and acted upon normally, sample code below (note that somefunction() below is just an example, in the original code it does real calculation instead of using rand())
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <errno.h>
#include <sys/time.h>
#include <unistd.h>
sigset_t sigs;
void setup_alarm()
{
printf("setting up signals\n");
sigemptyset(&sigs);
sigaddset(&sigs, SIGALRM);
sigprocmask(SIG_BLOCK, &sigs, NULL);
}
void wait_for_alarm(int interval)
{
printf("setting up alarm for %d seconds\n", interval);
alarm(interval);
printf("waiting for signal\n");
int sig_num = sigwait(&sigs, NULL);
// sigwaitinfo()
if (sig_num == 0)
{
printf("I received the alarm signal, breaking the wait\n");
}
else if (sig_num == EINVAL)
{
printf("some other error occurred");
perror("signal wait failed unexpectedly");
exit(1);
}
}
int somefunction()
{
srand(time(NULL));
return (rand() % 4) + 1;
}
int main(int argc, char *argv[])
{
int alarm_wait = 0;
setup_alarm();
while (1)
{
// do somework here
alarm_wait = somefunction();
// sleep for $alarm_wait or untill we receive SIGALARM
wait_for_alarm(alarm_wait);
}
return 0;
}
The results I'm getting is that when the execution reaches sigwait and I send the SIGINT signal(through ctrl-c) the program is not interrupted instead it keeps waiting until $alarm_wait has elapsed or until I send SIGALRM, what I want to do is have the logic only handles SIGALRM and every other signal should be handled normally(i.e SIGINT should interrupt the program even while it's waiting for SIGALRM signal)
Thanks to #Shawn for pointing out the second argument of sigwait I was able to solve my issue by also blocking SIGINT and using the second argument of sigwait to determine if the signal is SIGINT then execute exit(0)
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <errno.h>
#include <sys/time.h>
#include <unistd.h>
sigset_t sigs;
void setup_alarm()
{
printf("setting up signals\n");
sigemptyset(&sigs);
sigaddset(&sigs, SIGALRM);
sigaddset(&sigs, SIGINT);
sigprocmask(SIG_BLOCK, &sigs, NULL);
}
void wait_for_alarm(int interval)
{
printf("setting up alarm for %d seconds\n", interval);
alarm(interval);
printf("waiting for signal\n");
int sig;
int sig_num = sigwait(&sigs, &sig);
if(sig == SIGINT)
exit(0);
if (sig_num == 0)
{
printf("I received the alarm signal, breaking the wait\n");
}
else if (sig_num == EINVAL)
{
printf("some other error occurred");
perror("signal wait failed unexpectedly");
exit(1);
}
}
int somefunction()
{
srand(time(NULL));
return (rand() % 4) + 1;
}
int main(int argc, char *argv[])
{
int alarm_wait = 0;
setup_alarm();
while (1)
{
// do somework here
alarm_wait = somefunction();
// sleep for $alarm_wait or untill we receive SIGALARM
wait_for_alarm(alarm_wait);
}
return 0;
}
The code now works as i would expect, i'm not sure if this is the best solution since i'm only handling two signals and don't know how the rest of the signals are being handled(maybe some of these signals are important for the init system for example).
I will leave my answer unaccepted for sometime incase someone has a better solution.

Continue executing a stopped process with SIGALRM in C

the job is to continue executing a child process I stopped when I receive a SIGALRM signal.
so far I did the following, which doesn't seems to work:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
void handler(int sig)
{
printf("hello from the handler\n");
kill(getpid(),SIGCONT);
printf("child is continuing executing");
}
int main()
{
int pid1=fork();
signal(SIGALRM,handler);
if (pid1==0) {
kill(getpid(),SIGTSTP);
printf(" I am in the child\n");
} else {
printf("i am in the parent \n");
kill(pid1,SIGALRM);
}
}
I've tried many variations of the code, but printf("I am in the child"); is never executed.
Re: the question asked in a comment is ("how can I make the kill(pid1,SIGALRM) send the signal to the child?"). The call kill(pid1,SIGALRM) does send the signal to the child, but the child does not respond to it because it is stopped. The question asked is somewhat ambiguous, as it is not clear who "I" refers to in the phrase "when I receive a SIGALRM signal". If you want to have the child continue when the child receives a SIGALRM, you can't. You must send the child a SIGCONT before it will do anything. If you want the child to continue when the parent receives the SIGALRM, you could so something like:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
pid_t pid1;
void handler(int sig)
{
(void)sig;
if( pid1 ) {
kill(pid1, SIGCONT);
}
}
int main(void)
{
signal(SIGALRM, handler);
pid1 = fork();
if( pid1 == 0 ) {
kill(getpid(), SIGTSTP);
printf("Child continued\n");
} else {
alarm(1);
pause();
}
}

3 Player game in C using Signals

I have been trying to develop a 3 player game in C using signals but it is not giving desired output.
#define _POSIX_SOURCE //to use functionality from the POSIX.1 standard as ANCI C does not support kill()
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <signal.h>
#include <fcntl.h>
#include <time.h>
void action(){}
void child(char *);
int main(){
pid_t pid1, pid2, pid3;
printf("This is a 3-players game with a referee\n\n");
if((pid1=fork()) == 0) child("TOTO");
sleep(1);
if((pid2=fork()) == 0) child("TITI");
sleep(1);
if((pid3=fork()) == 0) child("TUTU");
sleep(1);
while(1){
signal(SIGUSR1, action);
printf("Refree: TOTO plays\n\n");
kill(pid1, SIGUSR1);
pause();
printf("Refree: TITI plays\n\n");
kill(pid2, SIGUSR1);
pause();
printf("Refree: TUTU plays\n\n");
kill(pid3, SIGUSR1);
pause();
}
}
void child(char *s){
int points=0, dice;
srand(time(NULL));
while(1){
signal(SIGUSR1, action); // block myself
pause();
sleep(1);
printf("%s: playing my dice\n", s);
dice = rand() % 10 + 1;
printf("%s: got %d points\n", s, dice);
points+=dice;
printf("%s: Total so far %d\n\n", s, points);
sleep(3);
if(points >= 100){
printf("%s: game over I won\n", s);
kill(0, SIGTERM);
}
kill(getppid(), SIGUSR1);
}
}
Output I get is:
This is a 3-players game with a referee
Refree: TOTO plays
TOTO: playing my dice
TOTO: got 8 points
TOTO: Total so far 8
Refree: TITI plays
TITI: playing my dice
TITI: got 2 points
TITI: Total so far 2
User defined signal 1
It never shows "TUTU" playing dice and terminates using User Defined Signal 1 which is registered as a blank signal. The program should terminate only after a player wins.
Any suggestions?
When the referee catches TOTO's signal, it's disposition is reset to SIG_DFL, so TITI's signal really kills him. The referee must call signal(SIGUSR1, action) three times per loop, before each kill().
An alternative is to #define _BSD_SOURCE (read the Portability section of man 2 signal carefully), which imposes a BSD semantics of not resetting a disposition

How to avoid scanf after my signal handler function in C?

I have this code:
#include <stdio.h>
#include <signal.h>
void signal_handler(int signal) {
printf("Caught signal in CHILD.\n");
}
int main(void) {
int s;
signal(SIGTSTP, signal_handler);
while(1){
printf("%s#%s/# ",getlogin(),get_current_dir_name());
scanf("%d",&s);
}
return 0;
}
when i run the code it prints:
something: ^ZCaught signal in CHILD.
As far i understand that the scanf doesn't execute when i press the ctr-z. Although after the printf inside my function it goes straight to the scanf, waits for input and then starts the loop again.Is there any way to avoid scanf when i press ctr-z and start the while loop again? I tried something like that
void signal_handler(int signal) {
printf("Caught signal in CHILD.\n");
printf("%s#%s/# ",getlogin(),get_current_dir_name());
}
but it didn't work. After the second printf goes straight to the scanf, waits for input and then starts the loop again. Can i, somehow, start the loop again?
The signal handler is interrupting scanf during its read of STDIN. However, because of the way you set signal disposition, the read system call restarts immediately upon return of the signal handler. That's why you are "stuck" in the scanf rather than back at the top of your loop.
One important thing you can do is to use sigaction rather than signal. This will force you to specify the behavior of interrupted calls: restart them or not?
The next thing to do is to limit your signal handlers to functions that are async-signal-safe, lest you risk misery.
As an aside, another change to make is to give us all the required includes (<unistd.h>?) and defines (_GNU_SOURCE ?) to make your program work.
As commented the worst solution should be:
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
void signal_handler(int signal) {
printf("Caught signal in CHILD.\n");
exit(1);
}
int main(void) {
int s;
signal(SIGTSTP, signal_handler);
while(1){
printf("test\n");
scanf("%d",&s);
}
return 0;
}
Better solution
#include <stdio.h>
#include <signal.h>
static volatile int keepRunning = 1;
void signal_handler(int signal) {
printf("Caught signal in CHILD.\n");
keepRunning = 0;
}
int main(void) {
int s;
signal(SIGTSTP, signal_handler);
while(keepRunning){
printf("test\n");
scanf("%d",&s);
}
return 0;
}
EDIT after comments
#include <stdio.h>
#include <signal.h>
static volatile int skipPrintf= 1;
void signal_handler(int signal) {
printf("Caught signal in CHILD.\n");
skipPrintf= 1;
}
int main(void) {
int s;
signal(SIGTSTP, signal_handler);
while(1){
if (skipPrintf == 0)
{
printf("test\n");
}
else
{
skipPrintf = 0;
}
scanf("%d",&s);
}
return 0;
}

How to send signals?

I created signals. One of them prints "1" 20 times. Another prints "2" 20 times.I want these signals to print their numbers in turn:1,2,1,2...But the program prints only "1".Can someone help me with that?
Run this code and see what when you send SIGUSR1 or SIGUSR2 to the pid printed.
#include <stdio.h>
#include <signal.h>
void handler1(int signal)
{
printf("Foo\n");
}
void handler2(int signal)
{
printf("Bar\n");
}
int main()
{
printf("PID: %d\n", getpid());
sigset(SIGUSR1,handler1);
sigset(SIGUSR2,handler2);
while (1);
return(0);
}

Resources