Hello I'm having issues with sending signals from the father process to the child process. The Child doesn't respond to the signed sent by the father process:
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
pid_t pid;
pid = fork();
if(pid > 0) {
printf("Hello, my son!\n");
sleep(5); /* Sleep for 5 seconds... */
kill(pid, SIGUSR1);
printf("Goodbye, son!\n");
}
else {
printf("Son is running\n");
pause(); /* Wait for some signal... */
printf("I received the signal!");
}
}
The son doesn't received the signal it only says it's running here is the output:
output
The default behavior when SIGUSR1 is received is termination, so the child never prints the message. To handle the signal, you can use sigaction:
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
void handle(int sig, siginfo_t *i, void *v) { return; }
int
main(void)
{
pid_t pid = fork();
if( pid > 0 ){
printf("Hello, my child!\n");
sleep(1); /* Sleep for 1 second. */
kill(pid, SIGUSR1);
printf("Goodbye, child!\n");
} else {
struct sigaction act;
memset(&act, 0, sizeof act);
act.sa_sigaction = handle;
if( sigaction( SIGUSR1, &act, NULL ) ){
perror("sigaction");
exit(1);
}
printf("Child is running\n");
pause(); /* Wait for some signal... */
printf("I received the signal!\n");
}
}
Related
I don't understand what is happening here, I have a parent process which handles the SIGINT signal and then makes a child. What I expect when I press Ctrl+C is that both processes will print "SIGINT received" and then continue but it turns out that the parent process dies after receiving SIGINT but the child is still there. I can't understand that.
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <sys/signal.h>
#include <string.h>
void handler (int sig) {
printf("SIGINT received\n");
}
void child() {
while (1) {
printf("I'm the child\n");
sleep(1);
}
exit(0);
}
int main(int argc, char *argv[]) {
struct sigaction act;
memset(&act, 0, sizeof(act));
act.sa_handler = &handler;
// Link SIGINT with the handler
sigaction(SIGINT, &act, NULL);
// Create child
if (fork() == 0) child();
wait(NULL);
return 0;
}
An example of execution:
$ ./test_signals
I'm the child
^CSIGINT received
I'm the child
SIGINT received
$ I'm the child
I'm the child
So both processes handle SIGINT but the parent dies while the child continues...
The parent process is blocked in the main function and upon receiving the signal, handles it and returns from the call to wait with an error.
The child is just looping in the while handling SIGINT. When handled code returns where it was (probably blocked in sleep) and it continues to loop.
That code may illustrates what happens:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <sys/signal.h>
#include <string.h>
#include <sys/errno.h>
void handler (int sig) {
printf("SIGINT received %d\n",getpid());
}
void child() {
while (1) {
printf("I'm the child\n");
sleep(1);
}
exit(0);
}
int main(int argc, char *argv[]) {
struct sigaction act;
memset(&act, 0, sizeof(act));
act.sa_handler = &handler;
// Link SIGINT with the handler
sigaction(SIGINT, &act, NULL);
// Create child
if (fork() == 0) child();
int r = wait(NULL);
if (r==-1 && errno==EINTR) printf("signal probably received in parent\n");
return 0;
}
Be aware that calling printf in a signal handler is forbidden.
I have two cods the first one is for the parent which sends a signal (SIGUSER1) to the child and when the child receive it he should print that he received it.
Parent code
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/types.h>
void sighand(int);
int main()
{
int cpid, ppid;
ppid = getpid();
printf("My process ID is %d\n", ppid);
FILE *fp1;
fp1 = fopen("cpid.txt", "w+");
cpid = fork();
if ( cpid == 0 ) {
printf("I am the child => PID = %d\n", getpid());
}
else
printf("I am the parent => PID = %d, child ID = %d\n", getpid(), cpid);
fprintf(fp1, "%d\n", cpid);
// kill(cpid, SIGUSR1);//id, signal, send
sigset(SIGUSR2, sighand);
return 0;
}
void sighand(int the_sig){
if (the_sig == SIGUSR2){
printf("sigusr2 received");
exit(1);
}
}
Child code
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/types.h>
void sighand1(int);
int main()
{
FILE *fp1;
int pid;
fp1 = fopen("cpid.txt", "r");
fscanf(fp1, "%d,", &pid);
sigset(SIGUSR1,sighand1);
while(1) {
printf("Waiting..");
sigpause(SIGUSR1);
}
return 0;
}
void sighand1(int the_sig)
{
if (the_sig == SIGUSR1){
printf("sigusr1 received");
exit(1);
}
}
When I start the code it prints that the process (child) was created then when I send a signal it wont do any thing the child stuck in a loop or the wait and the parent wont do anything can any one tell me where did i go wrong in my code or logic.
Your code has several problems:
You try to pass some pid through a file, but you can use the getppid() function (get parent id)
You have some child code, but it is not called
no signal is launched
So your code can be corrected this way:
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>
void parent_handler(int the_sig)
{
if (the_sig == SIGUSR2){
printf("sigusr2 received in parent\n");
}
}
void child_handler(int the_sig)
{
if (the_sig == SIGUSR1){
printf("sigusr1 received in child\n");
kill(getppid(), SIGUSR2);
exit(1);
}
}
int child_function()
{
/* prepare to receive signal */
sigset(SIGUSR1,child_handler);
while(1) {
printf("Waiting..");
fflush(stdout);
/* wait for signal */
sigpause(SIGUSR1);
}
return 0;
}
int main()
{
int cpid, ppid;
ppid = getpid();
printf("My process ID is %d\n", ppid);
cpid = fork();
if ( cpid == 0 ) {
printf("I am the child => PID = %d\n", getpid());
child_function();
return 0;
}
else
printf("I am the parent => PID = %d, child ID = %d\n", getpid(), cpid);
/* child will never reach this point */
sleep(1);
/* prepare parent to received signal */
sigset(SIGUSR2, parent_handler);
/* send signal to child */
kill(cpid, SIGUSR1);
sleep(1);
return 0;
}
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 to write a C program which creates a child and waits for a SIGHUP signal. After receiving that, it sends a signal to it's child. The child executes the default action of the received signal.
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
void sigint();
void sighup();
pid_t pid, pid_parent;
int main(int argc, char const *argv[])
{
if ((pid = fork()) < 0) {
perror("fail1!");
exit(1);
}
else if (pid == 0) {
signal(SIGINT, sigint);
while(1) pause();
exit(1);
}
signal(SIGHUP, sighup);
printf("PARENT's pid: %d\n", pid_parent = getpid());
while(1) pause();
return 0;
}
void sighup()
{
signal(SIGHUP,sighup);
kill(pid,SIGINT);
printf("PARENT(%d): I received a SIGHUP. I'll send something to my child(%d).\n",getpid(),pid);
printf("OK");
}
void sigint()
{
signal(SIGINT,sigint);
printf("CHILD: I received a SIGINT. I'll execute it.");
signal(SIGINT,SIG_DFL);
}
Seems like it doesn't work after kill(pid, SIGQUIT). And I really don't have ideas why.
I want to know, when my child process is exiting. But I don't want to block my application, so I use WNOHANG.
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void handler(int nsig) {
int status;
waitpid(-1, &status, WNOHANG);
printf("nsig=%i; status=%i\n", nsig, status);
if (WIFEXITED(status)) {
printf("Exited\n");
}
}
int main() {
struct sigaction act;
act.sa_handler = handler;
if (sigaction(SIGCHLD, &act, 0) < 0) {
fprintf(stderr, "sigaction failed\n");
exit(-1);
}
pid_t fpid;
fpid = fork();
if (fpid == 0) {
execlp("okular", "okular", 0);
}
while(1);
return 0;
}
It works fine if I close "okular" as usual.
$ ./test
nsig=17; status=0
Exited
But if I do something like
kill -STOP OKULAR_PID
I have the same output and that's wrong for me, because okular didn't exit in fact.
I think it is right, because SIGCHLD is defined as Child terminated or stopped as can be seen in this man page for signal. SIGCLD is a synonym for SIGCHLD.