Working on Linux, I want to catch the signal I have sent using kill in the child process and then print the loop but I don't know how.
I can't seem to get my code that catches the signal.
Here is my code so far:
#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>
int SHMSIZE = 9;
int alarmFlag = 0;
void main()
{
int shmid;
int *shm;
pid_t pid = fork();
if(pid == 0) {
pause();
shmid = shmget(4000, SHMSIZE, 0);
shm = shmat(shmid,0,0);
int i;
for(i=0;i<SHMSIZE;i++)
printf("<%d , ",shm[i]);
}
else
{
int *n;
shmid = shmget(4000,SHMSIZE,0666 | IPC_CREAT);
shm = shmat(shmid,0,0);
n = shm;
int i;
for(i=0;i<SHMSIZE;i++)
n[i] = i;
int result = kill(pid, SIGUSR1);
wait(NULL);
}
}
The pause() in your program on its own doesn't catch a signal, it just sleeps until a signal is delivered, but if that signal isn't caught (using sigaction() or signal(), as Jonathan Leffler wrote), it terminates the process. So, you have to add e. g. signal(SIGUSR1, catch); before pause(); and
void catch(int signum) { }
before main().
Related
I'm working on signal project get a file with 0, increase to the input (ex ./count 300 sample.txt) by using sync signals p1->p2->p3->p1, after they increase number by 1, the fall in to sleep and call next one.
but I got stuck with two problems
how to and where to implement increasing number process, in signal handling or main( 0 -> 1 -> 2 ... input )
don't know how to implement with sigwait() or sigprocmask() what's the difference? . can i choose either one to guarantee that they are synchronized? or should I just use sleep?
belows are code that I've been working on so far.
#include <stdio.h>
#include <signal.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
void sig_usr1(int signo)
{
char a;
sigset_t sigset, oldset;
sigemptyset (&oldset);
sigemptyset (&sigset);
sigaddset(&sigset, SIGUSR1);
sigprocmask(SIG_BLOCK, &sigset, &oldset);
fd =open("./sample.txt",O_RDWR);
pread (fd, a, sizeof(a));
if (argv[0]>a)
{a ++;
truncate ("./sample.txt", 0);
write(fd, a, sizeof(a));
}
}
int main (int argc, char** argv)
{
int fd;
int num=0;
struct sigaction usrsig ;
if(!(argv[0]>0))
printf("insert positive integer");
fd = open("./sample.txt",O_RDWR|O_CREAT|O_TRUNC);
write(fd, num ,sizeof(num);
pid_t child[3];
usrsig.sa_handler =sig_usr; // Parent
sigemptyset(&usrsig.sa_mask);
usrsig1.sa_flags = 0;
sigaction(SIGUSR1,&usrsig, 0);
for ( i=0; i<3; i++)
{
child[i] = fork();
if(child[i] == 0)
break;
}
pid_t prev;
if(i ==0) prev = getppid();
else prev = child[i-1];
kill(pid_prev, SIGUSR1)
}
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;
}
I have got a problem with dealing with some signals. I have got child processes with different group ID than a parent, and those kids are dealing with SIGALRM which parent is sending to them. Sometimes it works good, but sometimes it is called only once, and a child is becoming . Do you know where my mistake could be?
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <time.h>
int workers=2;
void sigalrm_handler(int signum)
{
printf("caught\n");
}
int main(int argc, char** argv) {
//region variables
char message[255]="Hello world!";
struct timespec sendSleep = {1,0};
struct sigaction new_a;
int pid;
for(int i=0; i<workers;i++)
{
pid=fork();
if(pid==0)
{
break;
}
}
if(pid==0)
{
//region sigalrm_handler
new_a.sa_handler = sigalrm_handler;
sigaction(SIGALRM, &new_a, NULL);
//endregion
while(1)
{
}
}
else
{
//region sigalrm_handler
new_a.sa_handler = SIG_IGN;
sigaction(SIGALRM, &new_a, NULL);
//endregion
nanosleep(&sendSleep,NULL);
for(int i=0; i<strlen(message); i++)
{
killpg(getpgrp(),SIGALRM);
printf("signal sent\n");
nanosleep(&sendSleep,NULL);
}
}
}
It is necessary to run it few times to get:
signal sent
signal caught
signal sent
signal sent
signal sent
I am trying to use signal to sync N processes then print out something.
Each child process register a handler which print "yo" and "hihi" when catching SIGUSR1.
I use kill(0, SIGUSR1) to trigger every process. Since the default action for catching SIGUSR1 is being killed, I set a do-nothing handler for the main process so that it will wait all child died.
The fork and send signal program will repeat for k times, I expect it will show out N*k times "yo" and "hihi". However, it doesn't show enough "yo" and "hihi" as I expect. The number of "yo" is different every execution.
Here is my code, and thanks for your help!
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <time.h>
#include <signal.h>
#include <sys/time.h>
#include <string.h>
#define N 3
int pid_id[N];
void handler2 (int signum)
{
printf("hihi\n");
}
void handler (int signum)
{
signal(SIGUSR2, handler2);
printf("yo\n");
raise(SIGUSR2);
}
void handler_do_nothing (int signum)
{
;
}
void child(int process_index)
{
struct sigaction sa;
/* Register */
memset(&sa, 0, sizeof(sa));
sa.sa_handler = handler;
sigaction(SIGUSR1, &sa, NULL);
printf("I am %d.\n", getpid());
pid_id[process_index] = getpid();
sleep(1);
exit(0);
}
int main()
{
int i, k, status;
pid_t pid[N];
pid_t pid_wait;
struct sigaction sa_main;
/* Register */ /* Main process will terminate if catch SIGUSR1 by default setting*/
memset(&sa_main, 0, sizeof(sa_main));
sa_main.sa_handler = handler_do_nothing;
sigaction(SIGUSR1, &sa_main, NULL);
/* Race k times */
for (k=0;k<3;k++)
{
for (i=0;i<N;i++)
{
pid[i] = fork();
if (pid[i]==0)
{
child(i);
}
}
// sleep();
kill(0, SIGUSR1);
for (i=0;i<N;i++)
{
do
{
pid_wait = waitpid(pid[i], &status, WNOHANG);
printf("I am waiting..\n");
sleep(1);
}while(pid_wait != pid[i]);
}
}
printf("all done\n");
return 0;
}
Your child processes are being signalled before they have had time (i.e. execution resource scheduled) to install the new signal handler.
This means that when the main program sends SIGUSR1, some subset of the child processes will still have handler_do_nothing installed.
If you want to wait until the child processes have all finished setting up, you will need to add some interprocess communication mechanism - e.g. the children could signal the parent process when they are ready.