How do you increment a count while using the sleep function? - c

Hey guys I seem to be lost. I am supposed to be able to increment a count in a child inside an infinite loop, and to have the count be printed every time the parent sends a signal, which should be every 1 second. I wrote my code but I thought that after using fork, the child and parent processes run at the same time, however this is not the case so I'm not sure how to tackle this problem. Any help would be great

What you are describing should work in theory.
Writing parallel code can be tricky, especially using fork(), if you're not familiar with the process.
Here is my suggestion: add a bunch of debug prints throughout your code, for example:
int pid = fork();
if(pid == -1) {
printf("Fork failed!\n");
} else if (pid) {
printf("I'm the parent!\n");
// Do stuff
printf("Parent exiting\n");
exit(0);
} else {
printf("I'm the child!\n");
// Do stuff
printf("Child exiting\n");
exit(0);
}
Then you can see if your program is behaving the way it should.
Also add a printf() statement to your signal handler so you can make sure it is being called.

The child process should be able to just run sleep(), and have the parent send SIGALRM to wake it up. Perhaps you made the child sit in a busy loop, consuming so much CPU that the parent didn't get to run as predicted.
Of course, answers to questions like these are way better if you show your code.

Related

waiting once after sending kill signal to multiple processes?

So I'm working on a project for one of my programming classes, and part of this assignment is about being able to launch process in the background, and being able to kill them when the user types "endb".
In order to kill the background processes, I have an array (PIDpool) which holds the PIDs of all the processes, and whenever the user input "endb", I go through this array of PIDs and kill them one by one.
Though, in order for this to work, I had to add a single wait after I sent a kill signal to each process. If I didn't, there would be a single defunct process left, and if I put a wait for each kill signal (by putting the wait within the killing loop), the program would hang.
While I'm happy to know my program seems to be working, I'm wondering why that wait is necessary, cuz it would seem to me that I would need either to wait for each process after killing them or wait for none at all...
Thanks in advance ^^
static void backgroundExecution(char** cmd_tokens){
if(!strcmp(cmd_tokens[0], "endb")){
for(size_t i = 0; i < arraySize(PIDpool); i++){
intptr_t PID = (intptr_t) arrayGet(PIDpool, i);
kill(PID, SIGKILL);
}
wait(NULL); // <------------ THIS WAIT HERE
arrayEmpty(PIDpool);
}else{
pid_t PID = fork();
if(PID == 0){
execvp(cmd_tokens[0], cmd_tokens);
}else{
arrayPushBack(PIDpool, (void*) (unsigned long) PID);
}
}
}
Look deeper into wait() and waitpid(). Wait simply waits for any child process to terminate, thus it works in your case.
You actually don't check whether each process has indeed stopped, nor whether the kill function returned an error.
As pointed out in the comments, your cast to intptr_t is incorrect, not sure what the type of PIDpool is but it should look like pid_t PIDpool[POOL_SIZE];

Allow a process to stop another process for a given time c

I want to know if there is a way to make a parent process stop his child for a given time using signal
for example:
pid_t pid = fork();
if(pid==0){
while(1){
//some code here
}
}else{
// some code to make child process stop for x seconds
}
You may use SIGSTOP and SIGCONT to stop and continue the process. In combination with some time delay function (e.g. sleep() ) you may get the desired effect.
You may check the example here: https://ostechnix.com/suspend-process-resume-later-linux/

Running fork inside a loop produces unexpected results (measuring process switch time)

I am writing a program to measure the time it takes to perform a process switch. In order to do this I am having a parent write one byte messages to its child and the child read it.
My problem is in this loop:
for(i=0; i<2; i++)
{
if(fork()==0) //child process, read
{
close(pipefd[1]);
read(pipefd[0]);
close(pipefd[0]);
}
else //parent process
{
close(pipefd[0]);
write(pipefd[1]);
close(pipefd[0]);
}
}
In order to test to see how often the fork was hitting the parent and child I put a printf statement in, and I got around 15 statements printed to the screen. How this is possible considering the loop should only run twice?
This is because each child process is going to create other processes.
After the if block is executed, each child will return at the beginning of the loop and fork() again, until i == 2 in all child processes.
Edit :
In order to avoid that, I suggest to use something like this :
if(fork() == 0)
{
//Do stuff
break;
}
Maybe this is not the most elegant way, but it should work.

does linux never end child process until the parent ends?

Please consider this code in c:
int main()
{
pid_t cpid;
cpid = fork();
if (cpid == -1)
{
perror("fork");
return 0;
}
if (cpid == 0)
{
printf("I'm child\n");
_exit(0);
}
else
{
while(1)
{
printf("I'm parent\n");
sleep(1);
}
}
return 0;
}
After running the code, I expect it to run child and exits it once it's done.
But when I run
pgrep executable_name
or
ps fax
it shows the child process id and I don't know if its just a history crap of working process or it really does not end/terminate the child process?
thanks in advance
The child will remain until its parent dies or the parent cleans it up with the wait system calls. (In the time between the child terminating and it being cleaned up, it is referred to as a zombie process.)
The reason is that the parent might be interested in the child's return value or final output, so the process entry stays active until that information is queried.
edit:
Example code for using the sigchld handler to immediately clean up processes when they die without blocking:
http://arsdnet.net/child.c
Be mindful of the fact that system calls (like sleep, select, or file read/writes) can be interrupted by signals. This is a normal thing you should handle anyway in unix - they fail and set errno to EINTR. When this happens, you can just try again to finish the operation. This is why my example code calls sleep twice in the parent - the first long sleep is interrupted by the child dying, then the second, shorter sleep lets us confirm the process is actually cleaned up before the parent dies.
BTW signal handlers usually shouldn't do much, they should return as soon as possible and avoid things that aren't thread safe; printfing in them is usually discouraged. I did it here just so you can watch everything as it happens.
You need to call wait() in the parent, otherwise the child process will never be reaped (it becomes a zombie).*
* Unless the parent itself also exits.

Waiting for processes in C

I've been reading the documentation on wait() and waitpid() and I'm still somewhat confused about how they work (I have gathered that wait(&status) is equivalent to waitpid(-1, &status, 0);). Below are some small snippets of code I'm working on. Please help me understand whether these snippets are written properly and if not then why not.
Goal 1: Reap all zombie children.
int reapedPid;
do {
reapedPid = waitpid(-1,NULL,WNOHANG);
} while (reapedPid > 0);
What I'm trying to do here is iterate through all the children, reap the child if it's finished, let it keep going if it's not, and when I run out of children then reapedPid == -1 and the loop exits. The reason I'm confused here is that I don't see how waitpid() is supposed to know which children have already been checked and which have not. Does it do any such check? Or will this approach not work?
Goal 2: Wait for all children to finish.
int pid;
do {
pid = wait(NULL);
} while (pid != -1);
Here I don't care what the resulting status is of the children - this should just keep waiting for every child process to finish, whether successfully or unsuccessfully, and then exit. I think this code is correct but I'm not sure.
Goal 3: Fork a child and wait for it to finish.
int pid = fork();
if (pid < 0) {
// handle error.
}
else if (pid == 0) {
// execute child command
}
else {
int status;
int waitedForPid = waitpid(pid,&status,0);
assert(waitedForPid == pid);
}
Here I'm just trying to fork the process and have the parent wait for the child to finish. I am not entirely sure if I should be passing in the 0 option here but it seemed like WNOHANG, WUNTRACED, and WCONTINUED were not really relevant to my goal.
It is the kernel's job to keep track of processes. Keeping track of dead processes is trivial. The kernel can tell which child processes have died but not yet been waited for, and will return one of those dead children on each call, until there are none left to report on. (Because of the WNOHANG option, there might still be children left to wait for, but none of the remaining children are dead, yet.)
This second loop is also fine and almost equivalent to the first. The difference is that it will hang waiting for all the children to die before returning the -1.
This third fragment is fine; the assertion will be true except in extraordinary circumstances (such as another thread in the program also waited for the child and collected the corpse). However, if you somewhere launched another process and let it run in the background, you might be collecting zombies, whereas with a modification of the other loops, you can collect the zombies and still wait for the correct child:
int pid = fork();
if (pid < 0)
{
// handle error.
}
else if (pid == 0)
{
// execute child command
}
else
{
int status;
int corpse;
while ((corpse = waitpid(-1, &status, 0)) > 0)
if (corpse == pid)
break;
}
For most of these, you should be able to easily code up some example programs and verify your understanding.
Goal 1: Reap all zombie children.
The reason I'm confused here is that I don't see how waitpid() is supposed to know which children have already been checked and which have not. Does it do any such check?
Once a child has exited, it can only be waited on once. So your loop will only get the exit status for child processes that have not yet been waited on (zombies).
For Goals 2 and 3, again, I would consider it a required exercise to code up an example to see how it works. For #2, I would instead suggest that your code should always keep track of all forked children, so that it can know exactly who to wait on. Your code for #3 looks good; no options are required. Remember to use the WEXITSTATUS and friends macros to get information from the status.
See also:
Waiting for all child processes before parent resumes execution UNIX

Resources