how can you pause child/parent processes in C and execute another function.
ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
how can you pause child/parent processes in C and execute another function.
hi,
the program i have written so far,spawns child processes each of which perform some simple exponential calculations to generate load.I am able to increase loads easily by just spawning more and more child processes.what i am trying to do now is to pause these child processes by pressing a keystroke button and execute a function to kill these child processes.I tried taking ctrl+c as an input to pause child processes,put in a signal handler to ignore this signal's default function(which is termination),and execute a kill function on a dynamic array that contains pids of chilren processes,to terminate child processes.But immediately on pressing ctrl +c ,and entering a desired load, the entire program terminates.what do I do to pause child processes and execute a function to decrease load??
Last edited by expeliarmus; 08-03-2007 at 08:08 AM.
immediately on pressing ctrl +c ,and entering a desired load, the entire program terminates.what do I do to pause child processes and execute a function to decrease load?
You fix the bug. There is no magic bullet.
Write a small, complete program which illustrates the problem. By "complete", I mean something that can compile right off the screen without the reader having to add any more #includes. By "small", I mean only complex enough to illustrate the problem, not your complete application.
Then post that code here. When you do, put it in CODE markers. To put it in CODE markers:
Click the Go Advanced button at the bottom of the editing window.
In the new editing window, highlight the code with your mouse.
Click the # icon at the top of the editing window.
You can't block a SIGKILL signal, which is what [Ctrl]+C will give you. You are thinking of SIGTERM. You can change what [Ctrl]+C does by setting the terminal properties, though. To stop the child processes, you will need to send a SIGSTOP signal to each one. You should also think about creating process groups to allow you to signal all processes in a group at one time.
ta0kira
thank you guys.wjevans,here's a sample code.the program computes a number say n,raised n times.
Code:
#include<stdio.h> /*a program to find out p^p,ptimes,that is if the input is 2,output gives,2^2^2.if
input is 3,output is 3^3^3,and so on */
#include<stdlib.h>
#include<math.h>
#include<unistd.h>
#include <sys/types.h>
#include <signal.h>
#include <sys/ipc.h>
#include <sys/shm.h>
/* ---------------------------------------------------------------- */
/* signal handler function prototypes */
/* ---------------------------------------------------------------- */
void SIGINT_handler(int); /* for SIGINT */
/* ---------------------------------------------------------------- */
/* global variable */
/* ---------------------------------------------------------------- */
int ShmID; /* shared memory ID */
pid_t *ShmPTR; /* shared memory pointer */
main()
{double load[3];
if (getloadavg(load, 3) != -1) /*getloadavg is the function used to calculate and obtain the load a
verage*/
{
printf("load average : %f , %f , %f\n", load[0],load[1],load[2]);
}
float m;
int n=2;
long double g,h,i,pid,j,p,x=1,a=1;
printf("enter the number whose exponential's is to be found\n");
scanf("%Lf",&p);
printf("enter the load average to be generated for the 1st minute\n");
scanf("%f",&m); /*reading the input*/
printf("finding (p^p^p^p....ptimes)\n");
h=p;
while(h>0) /*calculating the final exponent value*/
{x=x*p;
h--;
}
for(i=x;i>0;i--) /*calculating the actual answer*/
{a=a*p;
}
printf("the value is:%Lf\n",a);
getloadavg(load,3);
while(load[0]<m)
{
n=n*2; /*increasing the number of child process*/
goto x;
}
/*
printf("enter the number of child processes to be spwaned\n");
scanf("%Lf",&n);
*/
x:
while(load[0]<=m)
{
for(j=n;j>0;j--)
{
pid=fork(); /*creating the child process*/
if(pid>0)
wait(); /*making the parent process wait*/
if(pid <0)
{printf("error:cannot fork!!");
exit(1);
}
if (pid==0) /*child process*/
{ long double f=1;
MyKey = ftok(".", 's'); /* create a shared memory segment*/
ShmID = shmget(MyKey, sizeof(pid_t), IPC_CREAT | 0666);
ShmPTR = (pid_t *) shmat(ShmID, NULL, 0);
*ShmPTR = pid; /* save my pid there */
break;
printf("finding (p^p^p^p....ptimes)\n");
h=p;
while(h>0)
{x=x*p;
h--;
}
for(i=x;i>0;i--)
{f=f*p;
}
printf("the value is:%Lf\n",a);
if (getloadavg(load, 3) != -1)
{
printf("load average: %f, %f,%f\n",load[0],load[1],load[2]);
printf("The number of child processes created:%d\n",n);
}
pid_t pid = getpid();
key_t MyKey;
if (signal(SIGINT, SIGINT_handler) == SIG_ERR) {
printf("SIGINT install error\n");
exit(1);
}
MyKey = ftok(".", 's'); /* create a shared memory segment*/
ShmID = shmget(MyKey, sizeof(pid_t), IPC_CREAT | 0666);
ShmPTR = (pid_t *) shmat(ShmID, NULL, 0);
*ShmPTR = pid; /* save my pid there */
break;
}
}
getloadavg(load,3);
if(load[0]<m)
n=n*2; /*increasing the forked processes*/
continue;
}
}
void SIGINT_handler(int sig)
{
signal(sig, SIG_IGN);
printf("From SIGINT: just got a %d (SIGINT ^C) signal\n", sig);
signal(sig, SIGINT_handler);
}
expeliarmus, you have it right. ^C triggers SIGINT, not SIGKILL. But the rest of what ta0kira says is correct and useful:
Quote:
To stop the child processes, you will need to send a SIGSTOP signal to each one. You should also think about creating process groups to allow you to signal all processes in a group at one time.
Inspection of your code shows that the signal handler is installed in the child process, not in the parent process. Is this what you want?
Each child process will attach to the same shared memory segment, and place the content of variable pid there. One would think that the result would be that this shared memory segment would contain the pid of whatever child process was the latest one to get to this chunk of code. Is that what you want?
But variable pid is 0, since this is the child process, so each child process will be storing 0 into this shared memory segment. Is this what you want?
When a child process finishes doing child process stuff (the stuff inside the if(pid==0) block), it merrily continues with the getloadavg() call, the doubling of n, and the repeating of the whole while loop, which means that the child process will probably be doing a lot of fork()ing on its own. Is this what you want?
Inspection of your code hints to me (I might be wrong) that the following behavior wouldn't happen:
Quote:
immediately on pressing ctrl +c ,and entering a desired load, the entire program terminates.
It would seem to me that as soon as you type ^C, the program will terminate without letting you enter anything else, desired load or otherwise.
I wanted to run the program to test my hypothesis in the previous point, but didn't, for two reasons.
The program is incomplete. For one thing, MyKey is undeclared. For another, getloadavg() is undefined.
The program is far more complex than necessary to illustrate the problem. That makes it difficult for others to come along and help. It also discourages others from running the program on their systems; I'm certainly not going to run it, because for all I know, I might have dangling unremoved shared memory segments.
You may find that if you strip the program down so all it does is illustrate the problem, without all the exponentials and load averages and shared memory segments and stuff, just bare processes which loop, and no extraneous print statements to get in the way, you'll find the problem yourself, without having to wait for others to help. You'll certainly encourage them to read your code if they don't have to untangle it on the way.
As a side note, if this code ever becomes part of a complete product, scanf() is not the way to go for input. Use fgets to get each string and parse it completely, being paranoid about checking every byte of input.
So if you strip the program down, make it compilable and linkable, and still can't find the problem with the stripped-down program, post it and let's take a look.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.