C: Wait for brothers process termination - c

My program have to create n childs. When a signal is recieved a child is created. Then the first child wait for the others n-1 childs. The second one wait for the other n-2 childs and so on until the last child run and finish immediately.
I write this code, but it don't work and i get nephews.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
void func(int sign)
{
printf("received signal. I create a child\n");
}
int main(int argc, char*argv[])
{
if(argc!=3)
{
printf("error\n");
return 0;
}
int i,pid,status;
int n=atoi(argv[1]);
unsigned int m=(unsigned int)atoi(argv[2]);
signal(SIGALRM,func);
printf("i'm father: pid %d\n",getpid());
for(i=0; i<n; i++)
{
alarm(m);
pause();
switch(pid=fork())
{
case -1:
printf("error\n");
break;
case 0:
printf("i'm the hild numer %d, my pid is %d\n",i,getpid());
if(i!=n-1)
{
wait(NULL);
break;
}
else
{
printf("%d i have fnished\n",getpid());
exit(0);
}
break;
default:
wait(NULL);
break;
}
}
printf("finish\n");
return 0;
}

The way your code is structured, you are creating 2^N processes.
You need to change the code under:
default:
wait(NULL);
break;
to something that does not fork any more children after that. One way to do that is using a goto statement. Here's an updated version.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
void func(int sign)
{
printf("received signal. I create a child\n");
}
int main(int argc, char*argv[])
{
if(argc!=3)
{
printf("error\n");
return 0;
}
int i,pid,status;
int n=atoi(argv[1]);
unsigned int m=(unsigned int)atoi(argv[2]);
signal(SIGALRM,func);
printf("i'm father: pid %d\n",getpid());
for(i=0; i<n; i++)
{
alarm(m);
pause();
switch(pid=fork())
{
case -1:
printf("error\n");
break;
case 0:
printf("i'm the child numer %d, my pid is %d\n",i,getpid());
if(i!=n-1)
{
wait(NULL);
break;
}
else
{
printf("%d i have fnished\n",getpid());
exit(0);
}
break;
default:
wait(NULL);
goto done;
}
}
done:
printf("%d i have fnished\n",getpid());
return 0;
}

Related

How to stop a process from being closed after certain signal is sent?

I need to create a program, which will create child process that will handle processes. In case of SIGXCPU called, child process should close, but when other signal is received, process shouldn't close, but display information. How could I change signals_handler function to stop closing my process?
I call signals from second terminal window.
void signals_handler(int signal) {
psignal(signal,"\nRecived signal");
printf("Signal number is: %d\n", signal);
return;
}
void sig_XCPU(int signal() {
signal(XCPU, sig_XCPU);
}
...
int main(void)
{
if(fork() == 0) {
print("PID: %d", getpid();
signal(SIGXCPU, sig_xcpu)
for(int = 1; i < 65; i++) {
if(i != 24) //SIGXCPU number
signal(i, signals_handler);
}
sleep(100);
return 0;
}
}
return 0;
}
You can test like this:
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
void signal_handle(int sig) {
switch (sig) {
case SIGXCPU: {
char st[] = "child recesive SIGXCPU, quit\n";
write(STDOUT_FILENO, st, sizeof(st));
exit(EXIT_SUCCESS);
break;
}
case SIGINT: {
char st[] = "child recesive SIGINT\n";
write(STDOUT_FILENO, st, sizeof(st));
break;
}
default: break;
}
return;
}
void set_signal() {
signal(SIGXCPU, signal_handle);
signal(SIGINT, signal_handle);
}
int main() {
pid_t pid = fork();
if (pid == 0) { // child
set_signal();
char st[] = "child set signal\n";
write(STDOUT_FILENO, st, sizeof(st));
for (;;)
;
}
// parent
sleep(3); // wait child set_signal
// test SIGINT
{
char st[] = "parent send SIGINT\n";
write(STDOUT_FILENO, st, sizeof(st));
kill(pid, SIGINT);
}
sleep(3);
// test SIGXCPU
{
char st[] = "parent send SIGXCPU\n";
write(STDOUT_FILENO, st, sizeof(st));
kill(pid, SIGXCPU);
}
wait(NULL);
return 0;
}

how can I send a signal between a child and a parent processes in linux

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;
}

System Calls in C signals and fork

Hi I've this problem to solve with a functional program in C.
"Write a C program where a process F create a childprocess C.
The childprocess C waits the user to type the password, if is correct sends a signal SIGUSR1 to the father, if after 3 attempts the password is still incorrect it will send a SIGUSR2 signal to the father and terminate; if it receives from the father SIGUSR1 signal must stop viewing the "timeout" message.
His father after 30 seconds (if it has not received any signal from the child) must send the signal SIGUSR1 to the child and end with exit(1); if it receives the SIGUSR1 signal must end with exit(0); if it receives the signal SIGUSR2 must end with exit (2)."
I'm trying to solve it but I'm stuck. This is what I've done:
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <signal.h>
void fatherprocess(int mysignal){
if (mysignal == SIGUSR1) {
printf("ACCESS GRANTED!\n");
exit(0);
}
if (mysignal == SIGUSR2){
printf("ACCESS DISCARDED! More than 3 tentatives!\n");
exit(2);
}
}
void childprocess(int mysignal){
if (mysignal == SIGUSR1) {
printf("TIMEOUT\n");
exit(1);
}
}
int main(int argc, char *argcv[]){
int fatherpid, childpid;
char enteredpassword[], password[] = "test";
int i =0;
unsigned int time_to_sleep = 30;
fatherpid = getpid();
childpid = fork();
if (childpid == 0) {
printf("Child Process waiting for a password\n");
while (1){
if (i < 3) {
printf("Enter Password: ");
scanf("%s", enteredpassword);
if (enteredpassword == password)
signal(SIGUSR1, fatherprocess);
} else {
signal(SIGUSR2, fatherprocess);
exit(1);
}
i++;
}
} else {
printf("Father Process\n");
while(time_to_sleep){
time_to_sleep = sleep(time_to_sleep);
signal(SIGUSR1, childprocess);
}
}
return 0;
}
I've edited my program in this way:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <signal.h>
void fatherprocess(int mysignal, int fatherpid){
if (mysignal == SIGUSR1) {
printf("ACCESS GRANTED!\n");
kill(fatherpid, SIGUSR1);
exit(0);
}
if (mysignal == SIGUSR2){
printf("ACCESS DISCARDED! More than 3 tentatives!\n");
kill(fatherpid, SIGUSR2);
exit(2);
}
}
void childprocess(int mysignal, int childpid){
if (mysignal == SIGUSR1) {
printf("TIMEOUT\n");
kill(childpid, SIGUSR1);
exit(1);
}
}
int main(int argc, char *argcv[]){
int fatherpid, childpid;
char enteredpassword[] = "test", password[] = "test";
int i =0;
unsigned int time_to_sleep = 30;
fatherpid = getpid();
childpid = fork();
if (childpid == 0) {
printf("Child Process waiting for a password\n");
while (1){
if (i < 3) {
printf("Enter Password: ");
scanf("%s", enteredpassword);
if (strcmp(enteredpassword, password) == 0)
fatherprocess(SIGUSR1, fatherpid);
} else {
fatherprocess(SIGUSR2, fatherpid);
exit(1);
}
i++;
}
} else {
printf("Father Process\n");
while(time_to_sleep){
time_to_sleep = sleep(time_to_sleep);
childprocess(SIGUSR1, childpid);
}
}
return 0;
}
Now it works perfectly but I don't know if I've respected the exercise text.
As was mentioned in the comments (by Jonathan Leffler), you need to use the kill() system call (to send the signals) and register a signal handler using a call like sigaction(). I have linked these two calls to online manual pages that provide additional information about them.
Here's some code that demonstrates how these can be used towards achieving your stated goal. You will still need to add/modify the code for things like the prompts you want and the acceptable input string. Please note that I'm not claiming this to be the best way to do it, only that it's an example of how it could be done (it compiled and worked for me):
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
static void get_password(char* buf, int maxbuf)
{
fgets(buf, maxbuf, stdin);
}
static int is_password_correct(char* buf)
{
return buf[0] == 'a';
}
volatile int got_signal = 0;
volatile int child_signal = 0;
static void parent_sig_handler(int signum)
{
if (!got_signal)
{
got_signal = signum;
printf("parent_sig_handler: got sig %d\n", signum);
}
}
static void child_sig_handler(int signum)
{
if (!child_signal)
{
child_signal = signum;
printf("child_sig_handler: got sig %d\n", signum);
}
}
int main()
{
struct sigaction act;
sigfillset(&act.sa_mask);
act.sa_handler = parent_sig_handler;
sigaction(SIGALRM, &act, NULL);
sigaction(SIGUSR1, &act, NULL);
sigaction(SIGUSR2, &act, NULL);
pid_t child_pid = fork();
if (child_pid == -1)
{
perror("error forking");
exit(3);
}
if (child_pid == 0)
{
printf("child running\n");
act.sa_handler = child_sig_handler;
sigaction(SIGUSR1, &act, NULL);
pid_t parent_pid = getppid();
for (int i = 0; i < 3; ++i)
{
char passwd[64];
passwd[0] = '\0';
get_password(passwd, sizeof(passwd));
if (is_password_correct(passwd))
{
kill(parent_pid, SIGUSR1);
exit(0);
}
}
kill(parent_pid, SIGUSR2);
exit(2);
}
printf("parent running\n");
alarm(30); /* sets parent up to receive a SIGALRM signal in 30 seconds */
sigset_t sigmask;
sigemptyset(&sigmask);
while (!got_signal)
{
sigsuspend(&sigmask);
}
switch (got_signal)
{
case SIGALRM:
kill(child_pid, SIGUSR1);
exit(1);
case SIGUSR1:
exit(0);
case SIGUSR2:
exit(2);
default:
exit(3);
}
exit(3);
}

process communication with signls

I am trying to write a C program which has some number of processes. One of them sends a random signal in the range SIGRTMIN and SIGRTMAX to all other processes but I want this signal will be ignored in main process.I used the global variable to have randomized signal to ignore with SIG_IGN. It looks It is not helping because the main stops with real-time signal when wants to ignore the first randomized signal.
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <time.h>
volatile sig_atomic_t disarming_signal = 0;
void disarming_handler (int sig) {
disarming_signal = sig;
fprintf(stderr,"signal %d is handeled", disarming_signal);
}
int rand_range(int min_n, int max_n){
int rand_n = rand() % (max_n - min_n) + min_n;
return rand_n;
}
int sethandler (void (*f)(int), int sigNo) {
struct sigaction act;
memset(&act, 0, sizeof(struct sigaction));
act.sa_handler = f;
if (-1==sigaction(sigNo, &act, NULL))
return -1;
return 0;
}
void sigchld_handler(int sig){
pid_t pid;
for(;;){
pid=waitpid(0, NULL, WNOHANG);
if(pid==0) return;
if(pid<=0) {
if(errno==ECHILD) return;
perror("waitpid:");
exit(EXIT_FAILURE);
}
}
}
void usage(){
fprintf(stderr,"USAGE: sappartherroryst n\n");
fprintf(stderr,"n - number of Therrorysts\n");
}
void therroryst_work(){
int s,k,t;
srand(getpid());
s = rand_range(SIGRTMIN, SIGRTMAX);
t = rand_range(10, 20);
k = t;
if(sethandler(disarming_handler, s)){
perror("Seting therroryst handeler");
exit(EXIT_FAILURE);
}
fprintf(stderr, "[%d] I am therroryst. My disarming signal is [%d]. I will wait [%d] Sec.\n", getpid(), s, t);
while(k>0) {
k=sleep(k);
if(disarming_signal == s){
fprintf(stderr, "I got signal [%d]\n.",disarming_signal);
return ;
}
}
fprintf(stderr, "[%d] KABOOM\n",getpid());
exit(EXIT_SUCCESS);
}
void create_therrorysts(int n){
while(n-->0){
switch(fork()) {
case 0:
therroryst_work();
exit(EXIT_SUCCESS);
case -1:
perror("Fork():");
exit(EXIT_FAILURE);
}
}
}
void sapper_work(){
int sig_dis, i;
struct timespec t, tn = {1,0};
fprintf(stderr,"[%d] I am sapper.\n", getpid());
for(i=0;i<10;i++){
for(t=tn;nanosleep(&t,&t););
sig_dis = rand_range(SIGRTMIN, SIGRTMAX);
if(kill(0, sig_dis)<0){
perror("Disarming_send\n");
exit(EXIT_FAILURE);
}
fprintf(stderr,"I sended signal [%d].\n",sig_dis);
disarming_signal = sig_dis;
}
fprintf(stderr, "end of sending");
exit(EXIT_SUCCESS);
}
void create_sapper(){
switch(fork()) {
case 0:
sapper_work();
exit(EXIT_SUCCESS);
case -1:
perror("Fork():");
exit(EXIT_FAILURE);
}
}
int main(int argc, char** argv){
int n;
pid_t pid;
if(argc != 2){
usage();
return EXIT_FAILURE;
}
n = atoi(argv[1]);
if(n <= 0){
usage();
return EXIT_FAILURE;
}
if(sethandler(sigchld_handler, SIGCHLD)) {
perror("Seting parent SIGCHLD:");
exit(EXIT_FAILURE);
}
create_therrorysts(n);
create_sapper();
sleep(5);
for(;;) {
if(sethandler(SIG_IGN, disarming_signal)){
perror("Seting parent disarming111");
exit(EXIT_FAILURE);
}
}
for(;;){
pid=wait(NULL);
if(pid<0)
switch (errno){
case ECHILD:
return EXIT_SUCCESS;
case EINTR:
continue;
default:
perror("wait:");
exit(EXIT_FAILURE);
}
}
return EXIT_SUCCESS;
}
You have sleep(5) after the create_sapper and before sethandler(IGN). That means it's very likely that the signal is sent before your main process has ignored it.
EDIT: Adding comment from Jonathan Leffler into this answer as it is equally (or even more) important:
There's also a problem with setting the signal handler even if you put the sleep() after that loop - the parent doesn't get to see what the child chooses as disarming_signal.

How run a program in C for x minutes?

I am trying to run a program in C for x minutes. I need to make the child process go to sleep for that amount of time. Any help would be appreciated. Basically I am trying to understand how fork() and sleep() work. Here is my code snippet
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int i = fork();
printf("fork return value = %d\n", i);
printf("this is the time before sleep");
system("date +%a%b%d-%H:%M:%S");
printf("\n");
if (i==0){
sleep(120);
}
system("ps");
printf("this is the time after sleep");
system("date +%a%b%d-%H:%M:%S");
printf("\n");
}
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(void)
{
pid_t pid;
int rv=1;
switch(pid = fork()) {
case -1:
perror("fork"); /* something went wrong */
exit(1); /* parent exits */
case 0:
printf(" CHILD: This is the child process!\n");
printf(" CHILD: My PID is %d\n", getpid());
printf(" CHILD: My parent's PID is %d\n", getppid());
printf(" CHILD: I'm going to wait for 30 seconds \n");
sleep(30);
printf(" CHILD: I'm outta here!\n");
exit(rv);
default:
printf("PARENT: This is the parent process!\n");
printf("PARENT: My PID is %d\n", getpid());
printf("PARENT: My child's PID is %d\n", pid);
printf("PARENT: I'm now waiting for my child to exit()...\n");
wait(&rv);
printf("PARENT: I'm outta here!\n");
}
return 0;
}
Say thanks to Brian "Beej Jorgensen" Hall

Resources