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.
Related
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;
}
I have a program that starts a child (r.out), and that child has a time limit.
I want to know how to stop running r.out after passing the time limit.
I am running the code on Linux.
This is what I have so far:
#include <unistd.h>
#include <signal.h>
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#define TIME_LIMIT 1 //determine time limit
void my_function(); //supposed to include the submitted code
void alarm_handler(int);
int main()
{
if (sigaction(SIGALRM, NULL, NULL) == -1)
err(1, NULL);
signal(SIGALRM, alarm_handler); // assigning an alarm handler for SIGALRM
alarm(TIME_LIMIT); // install an alarm to be fired after TIME_LIMIT
system("./r.out"); //Running the file
alarm(0);
return 0;
}
void alarm_handler(int sig)
{
printf("%s" , "Time limit exceeded");
//Here i want a code to stop the r.out file
}
In order to kill the child, you need to know its pid. You can get it if you start the program with fork and exec instead of system.
In addition to a signal handler for SIGALRM, set up one for SIGCHLD (received when a child process finishes) as well. After calling alarm to set the timer, call pause. This function will return when you get either of the two signals.
In the signal handlers you should only set a global flag. Calling printf from within a signal handler can lead to undefined behavior.
After pause returns, check each of the two flags. If the timeout flag is set, you can terminate the child with kill.
In either case, call wait to reap the child process's pid.
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#define TIME_LIMIT 1 //determine time limit
void alarm_handler(int);
void child_handler(int);
int timeout = 0;
int child_done = 0;
int main()
{
pid_t pid = fork();
if (pid == -1) {
perror("fork failed");
exit(1);
} else if (pid == 0) {
// child process
execl("./r.out","r.out", NULL);
perror("exec failed");
_exit(1);
}
// set up the signal handlers after forking so the child doesn't inherit them
signal(SIGALRM, alarm_handler);
signal(SIGCHLD, child_handler);
alarm(TIME_LIMIT); // install an alarm to be fired after TIME_LIMIT
pause();
if (timeout) {
printf("alarm triggered\n");
int result = waitpid(pid, NULL, WNOHANG);
if (result == 0) {
// child still running, so kill it
printf("killing child\n");
kill(pid, 9);
wait(NULL);
} else {
printf("alarm triggered, but child finished normally\n");
}
} else if (child_done) {
printf("child finished normally\n");
wait(NULL);
}
return 0;
}
void child_handler(int sig)
{
child_done = 1;
}
void alarm_handler(int sig)
{
timeout = 1;
}
I create two children from the parent in the main program. The first and second child executes a program (signalSender) after their creation(alongside with the pid of the other child as an argument). signalSender has signal handler and is used for sending signal between process. The pid of the second child is given as zero as argument when first child executes signalShooter. The pid of the first child is given as argument when the second child executes sigShooter.
1) I want to find the pid of the first child via signal handler after second child sends the signal to first child. I tried to save it to global variable pid_t pid2 but it does not work.
2)I also have to send signal between these two children 100 times but i dont know where to use 'for loop' and ‘wait’ signal.
The main program:
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
int main()
{
pid_t pid1,pid2,wid;
char *my_args[5];
int aInt = 368
char str[15];
pid1 = fork();
if (pid1 < 0)
{
fprintf(stderr, ": fork failed: %s\n", strerror(errno));
exit(1);
}
if(pid1 == 0)
{
my_args[0] = "sigperf1";
my_args[1] = "0";
my_args[2] = NULL;
execv("signalSender",my_args);
fprintf(stderr,"signalSender cannot be executed...");
exit(-1);
}
pid2 = fork();
if(pid2 < 0)
{
fprintf(stderr, ": fork failed: %s\n", strerror(errno));
exit(1);
}
if(pid2 == 0)
{
sprintf(str, "%d", pid1);
my_args[0] = "sigperf1";
my_args[1] = str;
my_args[2] = NULL;
// printf("this is converted = %s\n",my_args[1]);
execv(“signalSender",my_args);
fprintf(stderr,"signalSender cannot be executed...");
exit(-1);
}
wid = wait(NULL);
}
The signalSender:
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <ctype.h>
pid_t pid2;
struct sigaction act;
void sighandler(int signum, siginfo_t *info, void *ptr)
{
printf("Received signal %d\n", signum);
printf("Signal originates from process %lu\n",
(unsigned long)info->si_pid);
pid2 = info->si_pid;
}
int main(int argc,char **argv)
{
memset(&act, 0, sizeof(act));
act.sa_sigaction = sighandler;
act.sa_flags = SA_SIGINFO;
sigaction(SIGUSR1, &act, NULL);
pid_t current, pidOther;
current = getpid();
pidOther = atol(argv[1]);
if(pidOther != 0) // we are in the second child
{
kill(pidOther,SIGUSR1); //sending signal from second child to first
}
if(pidOther == 0) // we are in the first child
{
kill(pid2,SIGUSR1);
}
return 0;
}
You have a synchronization issue here.
Both child processes start at roughly the same time. So you can't predict which one will kill the other first. If the first child runs kill first, it will pass 0 as the pid which will kill every process in the process group. Also, each child process quits immediately after calling kill, so one may exit before the other has a chance to send it a signal.
You need to introduce some type of synchronization method. A simple way to do this is to have the second process sleep briefly before calling kill to give the first process a chance to start up. Similarly, the first process should call pause, which will tell it to wait until it receives a signal.
Once you do that, then each process can call pause and kill in a loop to go back and forth.
if(pidOther != 0) // we are in the second child
{
sleep(1); // wait for first child to start
kill(pidOther,SIGUSR1); //sending signal from second child to first
for (i=0;i<5;i++) {
pause();
kill(pidOther,SIGUSR1);
}
}
if(pidOther == 0) // we are in the first child
{
pause(); // wait until we get a signal from the second child
kill(pid2,SIGUSR1);
for (i=0;i<5;i++) {
pause();
kill(pid2,SIGUSR1);
}
}
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;
}
I'm having some troubles using sigchld...
what I want to do is to create a child process with fork and make the child print and sleep a second for a couple of times... during these process I want to send signal to child (SIGSTOP and SIGCONTINUED) and I want the parent to print what the signal was... here's my code:
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
void handler (int i) {
int x;
waitpid(-1,&x, 0);
printf("WIFSTOPPED=%d, WIFCONTINUED=%d\n", WIFSTOPPED(x),WIFCONTINUED(x) );
}
int main(){
int x;
int q=fork();
if(q==0){
int i=0;
printf("%d\n",getpid());
while (i<20){
printf("%d\n", i++);
sleep(1);
}
_exit(0);
}
else {
signal(SIGCHLD, handler);
waitpid(-1,&x, 0);
while(WIFEXITED(x)!=1){
waitpid(-1,&x, 0);
sleep(1);
}
exit(0);
}
}
but it doesn't work beacause when I send a SIGSTOP or SIGCONTINUED to the child, the child stop and continue but the parent doesn't print anything
any suggestion?
Your handler shall not call waitpid again and you main while loop is also not correct : again you call waitpid twice the first time. And last, your waitpid call much declare to be interested in status changes (WUNTRACED option).
A much correct code could be :
void handler (int i) { // a handler just handle the fact some signal occured
printf("in handler\n");
}
int main(){
int x;
int q=fork();
if(q==0){
int i=0;
printf("%d\n",getpid());
while (i<20){
printf("%d\n", i++);
sleep(1);
}
_exit(0);
}
else {
signal(SIGCHLD, handler); // catch child status changes
do {
waitpid(-1,&x, WUNTRACED|WCONTINUED); // wait until child terminates or changes its status
if (WIFSTOPPED(x)|WIFCONTINUED(x)) // test what really happens
printf("STOPPED=%d, CONTINUED=%d\n", WIFSTOPPED(x),WIFCONTINUED(x) );
} while(!WIFEXITED(x));
exit(0);
}
}