I have a fork business and I have 4 child processes. I want to send a signal from parent process to each of 4 active child processes before they terminated. If child process id is odd, I send SIGUSR1, otherwise, I send SIGUSR2. I also want to print the receive time of each SIGUSR1 and SIGUSR2 signals in children processes.
Here is my source code:
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
void sigusr1();
void sigusr2();
void main()
{
int status;
pid_t pid[4];
int process_id;
for (int i = 0; i < 4; i++)
{
pid[i] = fork();
if (pid[i] == 0)
{
process_id = getpid();
if (process_id % 2 == 1)
{
signal(SIGUSR1, sigusr1);
sleep(1);
}
else
{
signal(SIGUSR2, sigusr2);
sleep(1);
}
exit(&status);
}
else
{
printf("\nPARENT: sending SIGUSR1\n\n");
kill(pid, SIGUSR1);
printf("\nPARENT: sending SIGUSR2\n\n");
kill(pid, SIGUSR2);
}
}
}
void sigusr1()
{
signal(SIGUSR1, sigusr1);
printf("CHILD: SIGUSR1\n");
time_t current_time;
char *c_time_string;
c_time_string = ctime(¤t_time);
printf("SIGUSR1 received time is %s", c_time_string);
}
void sigusr2()
{
signal(SIGUSR2, sigusr2);
printf("CHILD: SIGUSR2\n");
time_t current_time;
char *c_time_string;
c_time_string = ctime(¤t_time);
printf("SIGUSR2 received time is %s", c_time_string);
}
I got following output 4 times:
PARENT: sending SIGUSR1
PARENT: sending SIGUSR2
I cannot get signals in child processes. Can you help me to solve this issue?
When I compile your code, I get a lot of errors – some of them would be warnings except that I use -Werror
:
$ gcc -O3 -g -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes -Wstrict-prototypes -fno-common sig31.c -o sig31
sig31.c:8:1: error: function declaration isn’t a prototype [-Werror=strict-prototypes]
8 | void sigusr1();
| ^~~~
sig31.c:9:1: error: function declaration isn’t a prototype [-Werror=strict-prototypes]
9 | void sigusr2();
| ^~~~
sig31.c:11:6: error: function declaration isn’t a prototype [-Werror=strict-prototypes]
11 | void main()
| ^~~~
sig31.c:11:6: error: return type of ‘main’ is not ‘int’ [-Werror=main]
sig31.c: In function ‘main’:
sig31.c:34:14: error: passing argument 1 of ‘exit’ makes integer from pointer without a cast [-Werror=int-conversion]
34 | exit(&status);
| ^~~~~~~
| |
| int *
In file included from sig31.c:4:
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/stdlib.h:145:15: note: expected ‘int’ but argument is of type ‘int *’
145 | void exit(int) __dead2;
| ^~~
sig31.c:39:14: error: passing argument 1 of ‘kill’ makes integer from pointer without a cast [-Werror=int-conversion]
39 | kill(pid, SIGUSR1);
| ^~~
| |
| pid_t * {aka int *}
In file included from sig31.c:2:
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/signal.h:80:14: note: expected ‘pid_t’ {aka ‘int’} but argument is of type ‘pid_t *’ {aka ‘int *’}
80 | int kill(pid_t, int) __DARWIN_ALIAS(kill);
| ^~~~~
sig31.c:42:14: error: passing argument 1 of ‘kill’ makes integer from pointer without a cast [-Werror=int-conversion]
42 | kill(pid, SIGUSR2);
| ^~~
| |
| pid_t * {aka int *}
In file included from sig31.c:2:
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/signal.h:80:14: note: expected ‘pid_t’ {aka ‘int’} but argument is of type ‘pid_t *’ {aka ‘int *’}
80 | int kill(pid_t, int) __DARWIN_ALIAS(kill);
| ^~~~~
sig31.c: At top level:
sig31.c:47:6: error: function declaration isn’t a prototype [-Werror=strict-prototypes]
47 | void sigusr1()
| ^~~~~~~
sig31.c: In function ‘sigusr1’:
sig31.c:54:21: error: implicit declaration of function ‘ctime’ [-Werror=implicit-function-declaration]
54 | c_time_string = ctime(¤t_time);
| ^~~~~
sig31.c:54:19: error: assignment to ‘char *’ from ‘int’ makes pointer from integer without a cast [-Werror=int-conversion]
54 | c_time_string = ctime(¤t_time);
| ^
sig31.c: At top level:
sig31.c:59:6: error: function declaration isn’t a prototype [-Werror=strict-prototypes]
59 | void sigusr2()
| ^~~~~~~
sig31.c: In function ‘sigusr2’:
sig31.c:67:19: error: assignment to ‘char *’ from ‘int’ makes pointer from integer without a cast [-Werror=int-conversion]
67 | c_time_string = ctime(¤t_time);
| ^
cc1: all warnings being treated as errors
Most of those are issues I mentioned in comments — the complaint about assignment to ‘char *’ from ‘int’ makes pointer from integer without a cast [-Werror=int-conversion]
is because you didn't include <time.h>
.
Here is reworked code. It still ignores the issue of How to avoid using printf()
in a signal handler?.
/* SO 7601-6541 */
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <sys/wait.h>
static void sigusr1(int signum);
static void sigusr2(int signum);
int main(void)
{
pid_t pid[4];
struct sigaction sa = { 0 };
sa.sa_handler = sigusr1;
sigaction(SIGUSR1, &sa, 0);
sa.sa_handler = sigusr2;
sigaction(SIGUSR2, &sa, 0);
for (int i = 0; i < 4; i++)
{
pid[i] = fork();
if (pid[i] == 0)
{
sleep(1);
exit(0);
}
else
{
/* Snooze for 10 ms */
nanosleep(&(struct timespec){ .tv_sec = 0, .tv_nsec = 10000000 }, 0);
if (pid[i] % 2 == 1)
{
printf("PARENT: sending SIGUSR1 to %d\n", pid[i]);
kill(pid[i], SIGUSR1);
}
else
{
printf("PARENT: sending SIGUSR2 to %d\n", pid[i]);
kill(pid[i], SIGUSR2);
}
}
}
int corpse;
int status;
while ((corpse = wait(&status)) > 0)
printf("%d: child %d exited with status 0x%.4X\n", getpid(), corpse, status);
return 0;
}
static void sigusr1(int signum)
{
printf("CHILD %d: %d SIGUSR1\n", getpid(), signum);
time_t current_time = time(0);
printf("CHILD %d: SIGUSR1 received - time is %s", getpid(), ctime(¤t_time));
}
static void sigusr2(int signum)
{
printf("CHILD %d: %d SIGUSR2\n", getpid(), signum);
time_t current_time = time(0);
printf("CHILD %d: SIGUSR2 received - time is %s", getpid(), ctime(¤t_time));
}
When I run that, I get output such as:
PARENT: sending SIGUSR2 to 56842
CHILD 56842: 31 SIGUSR2
CHILD 56842: SIGUSR2 received - time is Fri Apr 14 14:14:24 2023
PARENT: sending SIGUSR1 to 56843
CHILD 56843: 30 SIGUSR1
CHILD 56843: SIGUSR1 received - time is Fri Apr 14 14:14:24 2023
PARENT: sending SIGUSR2 to 56844
CHILD 56844: 31 SIGUSR2
CHILD 56844: SIGUSR2 received - time is Fri Apr 14 14:14:24 2023
PARENT: sending SIGUSR1 to 56845
56841: child 56844 exited with status 0x0000
56841: child 56843 exited with status 0x0000
56841: child 56842 exited with status 0x0000
CHILD 56845: 30 SIGUSR1
CHILD 56845: SIGUSR1 received - time is Fri Apr 14 14:14:24 2023
56841: child 56845 exited with status 0x0000
Without the 10 ms nanosleep, the child processes were sometimes exiting with status 0x0004 — which indicates they died from signal SIGILL. I didn't experiment with smaller naps than 10 ms.