int ccount=0;
void child_handler(int sig){
int child_status;
pid_t pid = wait(&child_status);
ccount--;
}
void fork() {
pid_t pid[N];
int i, child_status;
ccount=N;
signal(SIGCHLD, child_handler);
for (i=0; i<N ; i++) {
if ((pid[i]=fork())==0) {
sleep(1); exit(0);
}
while (ccount>0) pause();
}
In this function, suppose that any one parent process receive the last SIGCHLD signal, Nth signal, between while and paust(). Then it cannot exit() because it cannot escape from while loop.
Then can I say that this program exits unnormally?
Related
My program creates multiple processes, the parent process will send SIGUSR1 to all child processes with the following function:
void sendtochild (struct system_ system, int sig) {
pid_t selfpid = getpid();
for (int i = 0; i < system.children; i++) {
if (system.pids[i] != selfpid && system.pids[i] != system.parent) {
kill(system.pids[i], sig);
}
}
}
The signal gets awaited in the following way:
sigset_t set, oset;
sigemptyset(&set);
sigaddset(&set, SIGUSR1);
if (sigprocmask(SIG_BLOCK, &set, &oset) < 0) {
perror("sigprocmask");
exit(EXIT_FAILURE);
}
printf("%d ", getpid());
fflush(stdout);
sigsuspend(&oset);
for some reason when looking at top the children are zombies instead of sleeping until the signal is delivered which is not the behavior I'm looking for.
In my following program i have two processes( the father and the child) both do the same thing but we want to figure out how will finish his task first. There is a randomized number of seconds both will sleep causing the challenge of who finishes first more random. Both are sending signals to the other process, when five signals have been recieved the process will then send a SIGTERM to the other process signaling that it has finished first. that other process will print that the opponent process has won. My problem is with sending that sigterm signal to the other process, ive tried kill function, singal function and dont know where is my mistake and what to try next. So any help would e=be appreciated below is my code:
//--------including--------------
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/types.h>
#include <signal.h>
#include <unistd.h>
//-------global----------------
int sig1_counter=0;
int sig2_counter=0;
//-------prototypes--------------
void catch_sigusr1(int sig_num) ;
void catch_sigusr2(int sig_num) ;
void do_son() ;
void do_dad() ;
//--------main------------------
int main (){
pid_t pid;
srand((unsigned)time(NULL));
signal(SIGUSR1, catch_sigusr1) ;
signal(SIGUSR2, catch_sigusr2) ;
pid = fork() ;
switch(pid) {
case -1 : perror("fork() failed") ;
exit(EXIT_FAILURE) ;
case 0 : do_son() ;
exit(EXIT_SUCCESS) ;
default: do_dad() ;
exit(EXIT_SUCCESS) ;
}
return EXIT_SUCCESS;
}
//-------functions-------------------
void do_son() {
int i ;
for (i=0;i<10;i++)
{
int sleep_time=rand()%4;
sleep(sleep_time);
int num=rand()%2;
if (num==0)
kill(getpid(), SIGUSR1) ;
else
kill(getpid(), SIGUSR2);
}
}
//---------------------------------
void do_dad() {
int i ;
for (i=0;i<10;i++)
{
int sleep_time=rand()%4;
sleep(sleep_time);
int num=rand()%2;
if (num==0)
kill(getpid(), SIGUSR1) ;
else
kill(getpid(), SIGUSR2);
}
}
//---------------------------------
void catch_sigusr1(int sig_num) {
signal(SIGUSR1, catch_sigusr1);
printf(" process %d got signal SIGUSR1\n", getpid()) ;
if (sig_num==SIGTERM)
{
printf("process %d win\n", getpid());
exit(EXIT_SUCCESS);
}
sig1_counter++;
if (sig1_counter==5)
{
printf(" process %d surrender\n", getpid()) ;
kill(getpid(),SIGTERM); // here we have a mistake
//signal(SIGTERM,catch_sigusr2); // !!!!!!!!!!!
exit(EXIT_SUCCESS);
}
}
//---------------------------------
void catch_sigusr2(int sig_num) {
signal(SIGUSR2, catch_sigusr2) ;
printf(" process %d got signal SIGUSR2\n", getpid()) ;
if (sig_num==SIGTERM)
{
printf("process %d win\n", getpid());
exit(EXIT_SUCCESS);
}
sig2_counter++;
if (sig2_counter==5)
{
printf(" process %d surrender\n", getpid()) ;
kill(getpid(),SIGTERM);
//signal (SIGTERM,catch_sigusr1);
exit(EXIT_SUCCESS);
}
}
Both your do_son() and do_dad() functions send signals to getpid(), which means they are signalling only themselves rather than each other.
In order to signal each other, you need:
do_dad() to send the signal to pid, the return value from fork() being the child PID; and
do_son() to send the signal to getppid(), the parent PID, noting the use of non-sexist terms in the system call :-)
In other words, something like this in your main function:
switch (pid = fork()) {
case -1:
perror("fork() failed");
break;
case 0:
do_both(getppid());
break;
default:
do_both(pid);
break;
}
The reason there's no distinct parent and child function any more is that the only difference is which PID gets signalled. Because you're passing that in as a parameter, you can combine the two functions:
void do_both(pid_t other) {
for (int i = 0; i < 10; i++) {
int sleep_time = rand() % 4;
sleep(sleep_time);
if ((rand() % 2) == 0)
kill(getpid(), SIGUSR1);
else
kill(getpid(), SIGUSR2);
}
}
currently I have the code like that:
void handler(int sig) {
int stat;
wait(&stat);
if (WIFEXITED(stat))
printf("%d", WEXITSTATUS(stat));
}
int main() {
int i;
pid_t pids[5];
signal(SIGCHLD, handler);
for (i=0; i<5; i++)
if ((pids[i] = fork()) == 0) {
printf("1");
while (1) ; /* inf loop */
}
for (i=0; i<5; i++)
kill(pids[i], SIGKILL);
sleep(1);
return 2;
}
All necessary head files were included such as <signal.h> and <stdlib.h>
I assume that I would at least get the exit status when running, but there is no output. Why is that?
But the child processes don't exit, they are killed. They are terminated by a signal. Use WIFSIGNALED to check if the process was killed by a signal, and WTERMSIG to get the signal number.
For a process to "exit" it has to either return from the main function, or call exit.
Okay so I am trying to teach myself on how to do signalling, and I came across a hiccup and I can't figure out what I'm doing wrong. What is going on right now is: it is executing the parent then goes to child and then back to parent.. It's not doing what I want it to do which is execute the parent (which the user defines the amount of time it runs) then kills it then go to child and run itself at the same amount of time.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h> // for wait
#include <sys/wait.h> // for wait
void action(int);
void action(int dummy){
sleep(1);
printf("Switching\n");
}
int main(int argc, char *argv[]){
pid_t pid;
int m = atoi(argv[1]), i = 0, x = 0;
if((pid=fork())>0){//parent
sleep(1);
while(i < m){
printf("hello %d\n", x);
x++;
kill(pid, SIGUSR1);
signal(SIGUSR1, action);
pause();
i++;
}
}
else
while(i < m){//child
//waitpid(getppid(), &status, 0); // wait for parent
signal(SIGUSR1, action);
pause();
printf("hi%d\n", x);
x++;
kill(getppid(), SIGUSR1);
i++;
}
}
What I want it to do is:
hello 0
hello 1
hello 2
hello 3
hello 4
Switching
hi 0
hi 1
hi 2
hi 3
hi 4
Any help is much appreciated!
You've got most of the pieces, they just need to be reordered a little bit.
install the signal handler in both processes before using kill
the parent should finish printing before signaling the child
the child can signal back after its done printing
void action(int dummy)
{
sleep(1);
printf("Switching\n");
}
int main(int argc, char *argv[])
{
int m = 3;
if (argc == 2)
m = atoi(argv[1]);
pid_t pid = fork(); // create the child process
signal(SIGUSR1, action); // set up the signal handler for both parent and child
if ( pid > 0 ) // the parent
{
for ( int i = 0; i < m; i++ )
{
sleep(1);
printf("hello %d\n", i);
}
kill( pid, SIGUSR1 ); // signal the child
pause(); // wait for the child to signal back
printf("All done\n");
}
else // the child
{
pause(); // wait for the signal from the parent
for ( int i = 0; i < m; i++ )
{
sleep(1);
printf("hi %d\n", i);
}
kill(getppid(), SIGUSR1); // signal the parent
}
}
I have some troubles:
it is not clear for me how to synchronise parent and child processes using signals, and this code doesn't work.
I thought that it should work like that: parent sends signal to child, child's pause() is end, child sends signal to parent, parent's pause() is end .. etc
why it is not so?
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
void handler_cp() {
}
void handler_pc() {
}
void child_proc() {
int i = 0;
for (; i < 50; ++i) {
pause();
kill(getppid(), SIGUSR2);
}
void parent_proc(pid_t ch) {
int j = 0;
for (; j < 50; ++j) {
kill(ch, SIGUSR1);
pause();
}
}
int main(int argc, char* argv[]) {
signal(SIGUSR1, handler_cp);
signal(SIGUSR2, handler_pc);
pid_t ch = fork();
if (ch == 0)
child_proc();
else
parent_proc(ch);
return 0;
}
The signal may arrive before pause is called, in which case it will deadlock. Using signals for synchronization is, in general, a very bad idea.
In the child_proc method, reverse the lines as :
kill(getppid(),SIGUSR2);
pause();
This will wake the parent before the child goes to sleep.