I am trying to terminate my c program with multiple functions after 20 seconds (kill all child and parent processes, close files). I tried alarm(), itimer(), clock(). It works when we only have a main and a handler function. clock() restarts from 0 in every function even if I keep the variables global.
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#include <stdlib.h>
#include <dirent.h>
#include <stdio.h>
#include <string.h>
#include <getopt.h>
#include<stdbool.h>
#include <ctype.h>
#include<sys/wait.h>
#include<signal.h>
#include <sys/mman.h>
#include<sys/time.h>
#define INTERVAL 2
int t=0;
void display_message()
{
printf("In the handler");
//kill(0,SIGKILL);
t=1;
}
void calling2()
{
signal(SIGALRM, display_message);
sleep(3);
}
void calling()
{
signal(SIGALRM, display_message);
alarm(2);
int i;
for(i=0;i<3;i++)
{
//printf("\nStarting fork for loop i=%d \n",i);
pid_t pID = fork();
if (pID == 0) // child
{
calling2();
if(t==1)
{
printf("we have exceeded 2 seconds killing the process");
kill(0,SIGKILL);
exit(0);
}
exit(0);
kill(pID,SIGKILL);
}
else if(pID>0)
{
// printf("\nhello from the father");
if(t==1)
{
printf("killing the process");
kill(0,SIGKILL);
exit(0);
}
printf("\nhello from the father");
}
}
}
As you can see I tried calling signal from different functions so it can catch the signal and the handler can execute but the handler is never executed.
EDIT: Tried this again
# include <unistd.h>
# include <sys/types.h>
# include <sys/stat.h>
# include <time.h>
# include <stdlib.h>
# include <dirent.h>
# include <stdio.h>
# include <string.h>
# include <getopt.h>
# include<stdbool.h>
# include <ctype.h>
# include<sys/wait.h>
# include<signal.h>
# include <sys/mman.h>
# include<sys/time.h>
# define INTERVAL 2
int t=0;
void display_message()
{
kill(0,SIGKILL);
t=1;
}
void calling2()
{
sleep(3);
}
void calling()
{
signal(SIGALRM, display_message);
int i;
for(i=0;i<3;i++)
{
pid_t pID = fork();
if (pID == 0) // child
{
calling2();
if(t==1)
{
printf("killing the process");
kill(0,SIGKILL);
exit(0);
}
exit(0);
}
else if(pID>0)
{
if(t==1)
{
printf("killing the process");
kill(0,SIGKILL);
exit(0);
}
printf("\nhello from the father");
}
}
}
int main()
{
signal(SIGALRM, display_message);
alarm(2);
calling();
}
O/P:
hello from the father
hello from the father
hello from the father
hello from the father
hello from the father
hello from the father
error: Failed with return code 22
Main problem is your main thread is finished before alarm signal is handled. You must let it live at least until alarm signal is delivered. Also as Jonathan Leffler adviced good indentation/spacing is really helpful.
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#include <stdlib.h>
#include <dirent.h>
#include <stdio.h>
#include <string.h>
#include <getopt.h>
#include <stdbool.h>
#include <ctype.h>
#include <sys/wait.h>
#include <signal.h>
#include <sys/mman.h>
#include <sys/time.h>
#define INTERVAL 2
int t=0;
void display_message()
{
kill(0,SIGKILL);
t=1;
}
void calling2()
{
sleep(3);
}
void calling()
{
signal(SIGALRM, display_message);
int i;
for(i=0;i<3;i++)
{
pid_t pID = fork();
if (pID == 0) // child
{
calling2();
if(t==1)
{
printf("killing the process");
kill(0,SIGKILL);
exit(0);
}
exit(0);
}
else if(pID>0)
{
if(t==1)
{
printf("killing the process");
kill(0,SIGKILL);
exit(0);
}
printf("\nhello from the father");
}
}
}
int main()
{
signal(SIGALRM, display_message);
alarm(2);
calling();
// wait until alarm callback before terminating main thread
sleep(100);
}
Related
i wrote the below code: after fork() function the parent send a signal to child. i think the child receive the signal and terminates.
i don't want the solution because i can solve it by two below ways.
i want to know what is the cause of this problem?
what i tried at first is below code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <wait.h>
#include <time.h>
#include <unistd.h>
#include <signal.h>
#define maxchild 1
int inchild=-1;
void sighandler(int signo){
char buffer[256];
int a,b=0;
switch(signo){
case SIGUSR1:
printf("SIGUSR1\n");
break;
case SIGUSR2:
printf("SIGUSR2\n");
break;
}
}
int main(){
pid_t ids[maxchild];
struct sigaction control;
control.sa_flags=0;
control.sa_handler=sighandler;
sigemptyset(&control.sa_mask);
sigaction(SIGUSR1,&control,NULL);
sigaction(SIGUSR2,&control,NULL);
for(int i=0;i<maxchild;i++){
ids[i]=fork();
printf("here %d\n",ids[i]);
if(ids[i]==0){
printf("in child\n");
inchild=i+1;
break;
}
}
while(inchild>=0) {
}
// sleep(1);
if(inchild==-1){
for(int i=0;i<maxchild;i++){
printf("child: %d\n parent: %d\n",ids[i],getpid());
kill(ids[i],SIGUSR1);
}
}
if (inchild==-1) wait(NULL);
return 0;
}
when i run the code so many times, i expect to see the "SIGUSR1" in output every time but mostly the output is:
here 17573 (or any other positive number)
child: 17573
parent: 17572
and then program terminates suddenly.
i understand i can solve it by two solution:
1. parent most sleep after fork() function:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <wait.h>
#include <time.h>
#include <unistd.h>
#include <signal.h>
#define maxchild 1
int inchild=-1;
void sighandler(int signo){
char buffer[256];
int a,b=0;
switch(signo){
case SIGUSR1:
printf("SIGUSR1\n");
break;
case SIGUSR2:
printf("SIGUSR2\n");
break;
}
}
int main(){
pid_t ids[maxchild];
struct sigaction control;
control.sa_flags=0;
control.sa_handler=sighandler;
sigemptyset(&control.sa_mask);
sigaction(SIGUSR1,&control,NULL);
sigaction(SIGUSR2,&control,NULL);
for(int i=0;i<maxchild;i++){
ids[i]=fork();
printf("here %d\n",ids[i]);
if(ids[i]==0){
printf("in child\n");
inchild=i+1;
break;
}
}
while(inchild>=0) {
}
sleep(1);
if(inchild==-1){
for(int i=0;i<maxchild;i++){
printf("child: %d\n parent: %d\n",ids[i],getpid());
kill(ids[i],SIGUSR1);
}
}
if (inchild==-1) wait(NULL);
return 0;
}
that it will work fine
i can comment the "kill(...)" line too to solve the problem:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <wait.h>
#include <time.h>
#include <unistd.h>
#include <signal.h>
#define maxchild 1
int inchild=-1;
void sighandler(int signo){
char buffer[256];
int a,b=0;
switch(signo){
case SIGUSR1:
printf("SIGUSR1\n");
break;
case SIGUSR2:
printf("SIGUSR2\n");
break;
}
}
int main(){
pid_t ids[maxchild];
struct sigaction control;
control.sa_flags=0;
control.sa_handler=sighandler;
sigemptyset(&control.sa_mask);
sigaction(SIGUSR1,&control,NULL);
sigaction(SIGUSR2,&control,NULL);
for(int i=0;i<maxchild;i++){
ids[i]=fork();
printf("here %d\n",ids[i]);
if(ids[i]==0){
printf("in child\n");
inchild=i+1;
break;
}
}
while(inchild>=0) {
}
// sleep(1);
if(inchild==-1){
for(int i=0;i<maxchild;i++){
printf("child: %d\n parent: %d\n",ids[i],getpid());
// kill(ids[i],SIGUSR1);
}
}
if (inchild==-1) wait(NULL);
return 0;
}
now i want to know the reason of problem.
i want to run the first code and see:
here (an positive number)
here 0
in child
child: (an positive number)
parent: (an positive number)
SIGUSR1
and the program must continue running until i press the Ctrl+c
(of course the order of line in output doesn't matter)
i didn't want to change the code, i want to know what is the cause of problem.
thank you in advance
If a process has a signal-handler installed this gets called on reception of the signal. This process is not ended then. So all the children are stuck in
while (inchild >= 0) {
}
As no child ends, the parent is blocking in wait().
To fix this replace the above snippet by
if (inchild >= 0) {
pause();
}
I'm trying to use date and wc with pipes on CentOS. I'm not able to printf that I'm in parent or child. Any help is appreciated.
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <assert.h>
#include <time.h>
#include <stdlib.h>
#include <semaphore.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
/* pipe1.c - send information through pipe. */
void syserr(char* msg)
{
printf("%s", msg);
}
void child(int pfd[]){
dup2(pfd[1],1);
execl("/bin/date", "date", 0);
}
void main()
{
int pfd[2], i, pid;
char str[] = "Hello World!\n";
if (pipe(pfd) == -1)
syserr("pipe");
printf("pfd[0] = %d, pfd[1] = %d\n", pfd[0], pfd[1]);
pid=fork();
switch(pid) {
case -1:
syserr("fork");
case 0:
{
printf("I'm child'");
child(pfd);
}
default:{ /* parent only */
if(pid!=0)
{
printf("I'm parent'");
dup2(pfd[0],0); //input
execl("/bin/wc", "wc", 0);
}/*default*/
} /*switch*/
}
}
Remember that <stdio.h> is buffered, and stdout is generally line-buffered, at least when it is a terminal. See setvbuf(3)
So you should either end each of your printf format control string with a \n or call fflush(3) at appropriate places. In particular, do a fflush(NULL); before your fork and your execl.
Also use perror on failure (i.e. replace every call to syserr by perror) to understand how system calls are failing. See perror(3) & errno(3) & strerror(3).
BTW, your main is incorrectly declared. You should enable all warnings and debug info when compiling (e.g. compile with gcc -Wall -Wextra -g). Improve your code to get no more warnings. Then use the debugger gdb ...
Notice that to avoid zombie processes, your parent process should use some waiting system call like waitpid(2) or wait(2) or wait4(2)
Works now. I had to add close(pfd[0]); in child, and close(pfd[1]); in parent.
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <assert.h>
#include <time.h>
#include <stdlib.h>
#include <semaphore.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
/* pipe1.c - send information through pipe. */
void child(int pfd[]){
printf("I'm in child func\n");
close(pfd[0]);
dup2(pfd[1],1);
execl("/bin/date", "date", 0);
}
int main(){
int pfd[2], pid;
if (pipe(pfd) == -1) perror("pipe");
printf("pfd[0] = %d, pfd[1] = %d\n", pfd[0], pfd[1]);
fflush(NULL);
pid=fork();
switch(pid) {
case -1:
perror("fork");
case 0:
{
printf("I'm child\n");
child(pfd);
}
default:{ /* parent only */
if(pid!=0){
printf("I'm daddy\n");
close(pfd[1]);
dup2(pfd[0],0); //input
execl("/bin/wc", "wc", 0);
}/*default*/
} /*switch*/
}
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'm supposed to write a program which creates 2 processes, connects between them with a pipe, and after a given time will end both processes and terminate.
one of the programs will write to the pipe, and the other will read from it and print it to STDOUT.
the reading process will be called first, then the pid will be passed to the second process so it will give SIGUSR1 signals to the first process, to tell it to read.
for some reason i never see the output in the terminal of the first process,
further more, it doesn't even print the line:"trying to exec1\n" which is where i call "execlp" for the process that prints.
here is the code for the 3 programs:
the main program:
#define STDERR 2
#define STDOUT 1
#define STDIN 0
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <signal.h>
#include <stdio.h>
void alarmHandler(int sig);
void systemError();
char * intToString(int num , char number[4]);
static pid_t processId1, processId2;
int main(int argc, char ** argv){
pid_t pid1, pid2;
sigset_t block_mask1;
struct sigaction exitSig;
sigfillset(&block_mask1);
exitSig.sa_handler = alarmHandler;
exitSig.sa_mask = block_mask1;
exitSig.sa_flags = 0;
sigaction(SIGALRM, &exitSig, NULL);
if (argc < 2){
systemError();
} else {
int x = atoi(argv[1]);
alarm(x);
}
int fields[2];
if (pipe(fields)){
systemError();
}
if ((pid1 = fork()) == 0){
printf("trying to exec1\n");
close(STDIN);
dup(fields[0]);
close(fields[0]);
close(fields[1]);
if(execlp("./ex2_inp", "./ex2_inp", NULL)){
systemError();
}
} else {
processId1 = pid1;
if ((pid2 = fork()) == 0){
char number[350];
printf("trying to exec2\n");
close(STDOUT);
dup(fields[1]);
close(fields[0]);
close(fields[1]);
char * pidString = intToString(processId1, number);
if(execlp("./ex2_upd","./ex2_upd",pidString, NULL)){
systemError();
}
} else{
processId2 = pid2;
}
}
close(fields[0]);
close(fields[1]);
pause();
return 1;
}
/***********************
* handler for alarm signal
*************************/
void alarmHandler(int sig){
kill(processId2, SIGINT);
kill(processId1, SIGINT);
exit(1);
}
/***********************
* turn pid to string
*************************/
char * intToString(int num , char number[350]){
sprintf(number, "%d", num);
return number;
}
ex2_inp:
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <signal.h>
#include <stdio.h>
void exitHandler(int sig);
void printHandler(int sig);
int main(int argc, char * argv[]){
sigset_t block_mask1, block_mask2;
struct sigaction exitSig, print;
sigfillset(&block_mask1);
sigfillset(&block_mask2);
exitSig.sa_handler = exitHandler;
print.sa_handler = printHandler;
print.sa_mask = block_mask2;
exitSig.sa_mask = block_mask1;
exitSig.sa_flags = 0;
print.sa_flags = 0;
sigaction(SIGINT, &exitSig, NULL);
sigaction(SIGUSR1, &print, NULL);
pause();
return 1;
}
void exitHandler(int sig){
printf("exiting1!\n");
close(1);
exit(1);
}
void printHandler(int sig){
char * buffer[80];
read(1, buffer, 80);
printf("%s", buffer);
}
ex2_upd:
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <signal.h>
#include <stdio.h>
void exitHandler(int sig);
int main(int argc, char * argv[]){
sigset_t block_mask1;
struct sigaction exitSig;
sigfillset(&block_mask1);
exitSig.sa_handler = exitHandler;
exitSig.sa_mask = block_mask1;
exitSig.sa_flags = 0;
sigaction(SIGINT, &exitSig, NULL);
printf("2's message\n");
kill(atoi(argv[1]), SIGUSR1);
pause();
return 1;
}
void exitHandler(int sig){
printf("exiting2!\n");
close(0);
exit(1);
}
thanks
ex2_upd.c:
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <signal.h>
#include <stdio.h>
void exitHandler(int sig);
int main(int argc, char * argv[]){
sigset_t block_mask1;
struct sigaction exitSig;
sigfillset(&block_mask1);
exitSig.sa_handler = exitHandler;
exitSig.sa_mask = block_mask1;
exitSig.sa_flags = 0;
sigaction(SIGINT, &exitSig, NULL);
printf("2's message\n");
kill(atoi(argv[1]), SIGUSR1);
sleep(1); /* This was pause - causing ex2_inp read() to wait forever, since read() on pipe needs to either fill buffer or END_OF_FILE, unless we make the filedescriptor in the read-end non-blocking via fcntl() */
return 1;
}
void exitHandler(int sig){
printf("exiting2!\n");
close(0);
exit(1);
}
ex2_inp.c:
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <signal.h>
#include <stdio.h>
void exitHandler(int sig);
void printHandler(int sig);
int main(int argc, char * argv[]){
sigset_t block_mask1, block_mask2;
struct sigaction exitSig, print;
sigfillset(&block_mask1);
sigfillset(&block_mask2);
exitSig.sa_handler = exitHandler;
print.sa_handler = printHandler;
print.sa_mask = block_mask2;
exitSig.sa_mask = block_mask1;
exitSig.sa_flags = 0;
print.sa_flags = 0;
sigaction(SIGINT, &exitSig, NULL);
sigaction(SIGUSR1, &print, NULL);
pause();
return 1;
}
void exitHandler(int sig){
printf("exiting1!\n");
close(1);
exit(1);
}
void printHandler(int sig){
char buffer[80]; /* removed * */
read(0, buffer, 80); /* stdin is fd=0, not 1 */
printf("-> %s <-\n", buffer); /* added \n, forces new-line */
}
I have a signal handler where I set ctrl+z/SIGTSTP to just be detected by the program. But when I want to change the signal handler of ctrl+z/SIGTSTP to its default behavior in the child process, the ctrl+z doesn't change. Is there a proper to change signal handlers?
#include <stdio.h>
#include <signal.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <sys/types.h>
#include <string.h>
#include <unistd.h>
void handler(int sig_num)
{
printf("detected %d\n",sig_num);
}
int main()
{
int x;
signal(SIGTSTP,handler);
pid_t pid = fork();
if(pid == 0)
{
signal(SIGTSTP,SIG_DFL);
printf("in child process \n");
while(1);
}
else if(pid > 0)
{
printf("running parent\n");
printf("waiting for my child to run\n");
wait(&x);
exit(0);
}
return 0;
}