I have a signal handler where I set ctrl+z/SIGTSTP to just be detected by the program. But when I want to change the signal handler of ctrl+z/SIGTSTP to its default behavior in the child process, the ctrl+z doesn't change. Is there a proper to change signal handlers?
#include <stdio.h>
#include <signal.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <sys/types.h>
#include <string.h>
#include <unistd.h>
void handler(int sig_num)
{
printf("detected %d\n",sig_num);
}
int main()
{
int x;
signal(SIGTSTP,handler);
pid_t pid = fork();
if(pid == 0)
{
signal(SIGTSTP,SIG_DFL);
printf("in child process \n");
while(1);
}
else if(pid > 0)
{
printf("running parent\n");
printf("waiting for my child to run\n");
wait(&x);
exit(0);
}
return 0;
}
Related
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();
}
}
I am trying to terminate my c program with multiple functions after 20 seconds (kill all child and parent processes, close files). I tried alarm(), itimer(), clock(). It works when we only have a main and a handler function. clock() restarts from 0 in every function even if I keep the variables global.
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#include <stdlib.h>
#include <dirent.h>
#include <stdio.h>
#include <string.h>
#include <getopt.h>
#include<stdbool.h>
#include <ctype.h>
#include<sys/wait.h>
#include<signal.h>
#include <sys/mman.h>
#include<sys/time.h>
#define INTERVAL 2
int t=0;
void display_message()
{
printf("In the handler");
//kill(0,SIGKILL);
t=1;
}
void calling2()
{
signal(SIGALRM, display_message);
sleep(3);
}
void calling()
{
signal(SIGALRM, display_message);
alarm(2);
int i;
for(i=0;i<3;i++)
{
//printf("\nStarting fork for loop i=%d \n",i);
pid_t pID = fork();
if (pID == 0) // child
{
calling2();
if(t==1)
{
printf("we have exceeded 2 seconds killing the process");
kill(0,SIGKILL);
exit(0);
}
exit(0);
kill(pID,SIGKILL);
}
else if(pID>0)
{
// printf("\nhello from the father");
if(t==1)
{
printf("killing the process");
kill(0,SIGKILL);
exit(0);
}
printf("\nhello from the father");
}
}
}
As you can see I tried calling signal from different functions so it can catch the signal and the handler can execute but the handler is never executed.
EDIT: Tried this again
# include <unistd.h>
# include <sys/types.h>
# include <sys/stat.h>
# include <time.h>
# include <stdlib.h>
# include <dirent.h>
# include <stdio.h>
# include <string.h>
# include <getopt.h>
# include<stdbool.h>
# include <ctype.h>
# include<sys/wait.h>
# include<signal.h>
# include <sys/mman.h>
# include<sys/time.h>
# define INTERVAL 2
int t=0;
void display_message()
{
kill(0,SIGKILL);
t=1;
}
void calling2()
{
sleep(3);
}
void calling()
{
signal(SIGALRM, display_message);
int i;
for(i=0;i<3;i++)
{
pid_t pID = fork();
if (pID == 0) // child
{
calling2();
if(t==1)
{
printf("killing the process");
kill(0,SIGKILL);
exit(0);
}
exit(0);
}
else if(pID>0)
{
if(t==1)
{
printf("killing the process");
kill(0,SIGKILL);
exit(0);
}
printf("\nhello from the father");
}
}
}
int main()
{
signal(SIGALRM, display_message);
alarm(2);
calling();
}
O/P:
hello from the father
hello from the father
hello from the father
hello from the father
hello from the father
hello from the father
error: Failed with return code 22
Main problem is your main thread is finished before alarm signal is handled. You must let it live at least until alarm signal is delivered. Also as Jonathan Leffler adviced good indentation/spacing is really helpful.
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#include <stdlib.h>
#include <dirent.h>
#include <stdio.h>
#include <string.h>
#include <getopt.h>
#include <stdbool.h>
#include <ctype.h>
#include <sys/wait.h>
#include <signal.h>
#include <sys/mman.h>
#include <sys/time.h>
#define INTERVAL 2
int t=0;
void display_message()
{
kill(0,SIGKILL);
t=1;
}
void calling2()
{
sleep(3);
}
void calling()
{
signal(SIGALRM, display_message);
int i;
for(i=0;i<3;i++)
{
pid_t pID = fork();
if (pID == 0) // child
{
calling2();
if(t==1)
{
printf("killing the process");
kill(0,SIGKILL);
exit(0);
}
exit(0);
}
else if(pID>0)
{
if(t==1)
{
printf("killing the process");
kill(0,SIGKILL);
exit(0);
}
printf("\nhello from the father");
}
}
}
int main()
{
signal(SIGALRM, display_message);
alarm(2);
calling();
// wait until alarm callback before terminating main thread
sleep(100);
}
I must create a program in C who will be communicate between two process by SIGUSR1. This program must will reply back when send and receive signal. I have the code below, but he just sends a signal, why does the receiving function not work?
IMG
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
void send_SIGUSR1();
void main()
{
int pid;
if ((pid = fork()) < 0) {
perror("Fork");
exit(1);
}
if (pid == 0) {
signal(SIGUSR1, send_SIGUSR1());
}
else
{
printf("\nPARENT: sending SIGUSR1\n\n");
kill(pid, SIGUSR1);
}
}
void send_SIGUSR1()
{
signal(SIGUSR1, send_SIGUSR1);
printf("CHILD: I have received a SIGUSR1\n");
}
I have a parent process that is spawning X number of child processes (player) based off the first argument passed to the program. After each child is spawned it sends them a signal. For now all I want the children to do it print they received the signal and exit, but they don't seem to get the signal from the parent. Are the children not getting the signal or am I handling it wrong?
Parent:
#define _POSIX_SOURCE
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
void reciveCard() {
write(1, "signal recived\n", 15);
exit(0);
}
int main(int argc, char **argv) {
int numPlayers, i;
int *kpids;
numPlayers = atoi(argv[1]);
kpids = malloc(numPlayers * sizeof(int));
signal(SIGUSR1, SIG_IGN);
for(i = 0; i < numPlayers; i++) {
if((kpids[i] = fork()) == 0) {
if(execlp("./player\0", "./player\0", (char *) NULL) == -1) {
printf("error\n");
exit(1);
}
}
}
for(i = 0; i < numPlayers; i++) {
printf("%d\n", kpids[i]);
kill(kpids[i], SIGUSR1);
}
wait(NULL);
return 0;
}
Child:
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
void reciveCard() {
write(1, "signal recived\n", 15);
exit(0);
}
int main() {
signal(SIGUSR1, reciveCard);
while(1) {
sleep(1);
}
return 0;
}
You have a race condition.
The parent program does the fork calls so fast that it falls into the kill loop before any child has a chance to do the execlp.
Thus, the child can't set up the handler fast enough. That is, when the signal comes in, the child is still ignoring it because of the parent's SIG_IGN call that it has inherited.
Now, after the execlp, the child will set up the handler, but the signal has already occurred, so the the handler will never be called.
To see this, add a sleep(1) between the two parent loops and it should work.
I need to send a signal to a child process 3 times.
The problem is that the child only receives the signal once and then transforms into a zombie.
The expected output would be:
I'm the child 11385 and i received SIGUSR1
I'm the child 11385 and i received SIGUSR1
I'm the child 11385 and i received SIGUSR1
But the real output is:
I'm the child 11385 and i received SIGUSR1
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
void my_handler()
{
printf("\n I'm the child %i and i received SIGUSR1\n", getpid());
}
int main (int argc, char **argv) {
int *array;
int N = 10;
int i;
pid_t pid1;
array=(int*)malloc(sizeof(int)*N);
signal(SIGUSR1,my_handler);
for (i = 0; i< N; i++)
{
pid1 = fork();
if(pid1 < 0)
{
exit(EXIT_FAILURE);
}
else if (pid1 > 0)
{
array[i]= pid1;
}
else
{
sleep(100);
exit(EXIT_SUCCESS);
}
}
i=0;
while(i<3) // I need to call the son 3 times
{
kill(array[1], SIGUSR1);
i++;
}
}
When the child receives the signal, it is probably waiting for the sleep to terminate. The first signal will interrupt the sleep even if the time hasn't expired, causing it to return with errno set to EINTR. If you want it to keep sleeping, you need to call sleep again.
your parent process exited without wait()ing for the child
The signals could be sent to fast, I added a short delay
i added more delays
the correct signature for a signal handler is void handler(int signum) This is crucial, because the handler is called with an argument, and the stack layout is different for signal handlers.
you should not call printf() from a signal handler, it is not async safe.
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
char pidstr[10];
char massage[]=" I'm the child and i received SIGUSR1\n";
#define CNT 1
void my_handler(int signum)
{
write(0, massage, strlen(massage));
}
int main (int argc, char **argv) {
int i , err, status;
pid_t pid1;
int array[CNT];
signal(SIGUSR1, my_handler);
for (i = 0; i< CNT; i++) {
pid1 = fork();
if(pid1 < 0) { exit(EXIT_FAILURE); }
else if (pid1 > 0) {
printf("ChildPid=%d\n", pid1 );
array[i]= pid1;
}
else
{ // child
// signal(SIGUSR1, my_handler);
sprintf(pidstr,"[%d]", getpid() );
memcpy (massage,pidstr, strlen(pidstr));
sleep(10);
printf("Unslept\n");
sleep(10);
printf("Unslept\n");
sleep(10);
printf("Unslept\n");
exit(EXIT_SUCCESS);
}
}
sleep(10);
for (i=0; i<3; i++) {
err = kill(array[0], SIGUSR1);
printf("Err=%d:%d\n", err, (err) ? errno: 0 );
sleep(1);
}
while ( (pid1=wait( &status)) != -1){
printf("[Parent] Reaped %d\n", pid1);
}
return 0;
}