waitpid() and fork() to limit number of child processes - c++

My program is supposed to limit the number of child processes to 3.
With the code below, waitpid stalls my parent process so I can't create more child processes after the first one. If I don't use waitpid then I don't know when a child process quits to decrease the number of alive processes.
int numProcs = 0;
while(1==1) {
/*
* inserts code that waits for incoming input
*/
numProcs++;
pid = fork();
if (pid == 0) {
doStuff(); // may exit anytime, based on user input
} else {
if (numProcs > 3) {
wait(&status);
numProcs--;
} else {
waitpid(pid, &status, 0); // PROBLEM!
numProcs--;
}
}
}
I've been searching for this problem the whole day. Can somebody help?

At the risk of being obvious, you basically want to just drop the else clause. The logic you're looking for is something like:
int max_active = 3; // or whatever
int number_active = 0;
bool done = false;
for (; !done; ++number_active) {
// wait for something to do;
GetSomeWork();
// wait for something to finish, if necessary.
for (; number_active >= max_active; --number_active)
wait(&status);
pid = fork();
if (pid < 0)
ReportErrorAndDie();
if (pid == 0)
DoTheWorkAndExit();
}
This actually lets you change the value of max_active without restarting, which is the only justification for the for loop around the wait() call.
The obvious complaint is that number_active in my version doesn't actually tell you how many processes are active, which is true. It tells you how many processes you haven't wait()'ed for, which means that you might keep some zombies (but the number is limited). If you're constantly running at or close to the maximum number of tasks, this doesn't matter, and unless your maximum is huge, it doesn't matter anyway, since the only Design Requirement was that you don't use more than the maximum number of tasks, and consequently you only have to know that the number active is not more than the maximum.
If this really bothers you and you want to clean the tasks up, you can put:
for (; waitpid(-1, &status, WNOHANG) > 0; --number_active) {}
before the other for loop, which will reap the zombies before checking if you need to block. (I can't remember if waitpid(-1, &status WNOHANG) returns an error if there are no processes at all, but in any event there's no point continuing the loop on an error.)

You have two problems with your code, but the second one is masked by the first.
Your immediate problem is that waitpid(pid, &status, 0); will block until the process with the specified pid terminates. You want to add the WNOHANG option as a third parameter to the waitpid() call. That will ensure that the call dosn't block.
This will add a new problem: You will have to check for yourself is any child process have terminated. You can do that using the WIFEXITED macro:
} else {
waitpid (-1, &status, WNOHANG);
if (WIFEXITED(status)) {
numProcs--;
}
}
The second problem is that your original code only waits for the latest pid to be created. You should instead wait for -1, which is all child processes.

Related

Let threads execute untill a specific point, wait for the rest to get there, execute the remaining code sequentially

I have some code that needs to benchmark multiple algorithms. But before they can be benchmarked they need to get prepared. I would like to do this preparation multi-threaded, but the benchmarking needs to be sequential. Normally I would make threads for the preparation, wait for them to finish with join and let the benchmarking be done in the main thread. However the preparation and benchmarking are done in a seperate process after a fork because sometimes the preparation and the benchmarking may take too long. (So there is also a timer process made by a fork which kills the other process after x seconds.) And the preparation and benchmarking have to be done in the same process otherwise the benchmarking does not work. So I was wondering if I make a thread for every algorithm if there is a way to let them run concurrently until a certain point, then let them all wait untill the others reach that point and then let them do the rest of the work sequentially.
Here is the code that would be executed in a thread:
void prepareAndBenchmark(algorithm) {
//The timer thread that stops the worker after x seconds
pid_t timeout_pid = fork();
if (timeout_pid == 0) {
sleep(x);
_exit(0);
}
//The actual work
pid_t worker_pid = fork();
if (worker_pid == 0) {
//Concurrently:
prepare(algorithm)
//Concurrently up until this point
//At this point all the threads should run sequentially one after the other:
double result = benchmark(algorithm)
exit(0);
}
int status;
pid_t exited_pid = wait(&status);
if (exited_pid == worker_pid) {
kill(timeout_pid, SIGKILL);
if(status == 0) {
//I would use pipes to get the result of the benchmark.
} else {
//Something went wrong
}
} else {
//It took too long.
kill(worker_pid, SIGKILL);
}
wait(NULL);
}
I have also read that forking in threads migth give problems, would it be a problem in this code?
I think I could use mutex to have only one thread benchmarking at a time, but I don't want to have a thread benchmarking while others are still preparing.

Creating new processes with fork() vs exec()

#1 code
int child_pid;
for (int i = 0; i < 3; i++)
{
child_pid = fork();
if (child_pid == 0)
{ sleep(10); }
else
{ wait(&status); }
}
execlp("sleep","sleep","20",(char*)NULL);
#2 code
int child_pid;
for (int i = 0; i < 5; i++)
{
child_pid = fork();
if (child_pid == 0)
{ sleep(1); }
else
{ wait(&status);
execlp("sleep","sleep","20",(char*)NULL); }
}
Can someone explain to me what is happening in these codes?
I understand fork() returns a zero to a newly created child process. That's why I don't understand why in #2 code the else branch is also being executed? Execlp replaces the calling process image with a new process image, but what does this really mean?
EDIT:
The answer is that the first code will create 8 processes, but I'm not able to understand how? And why will the first code finish 230 seconds? How does exec affect this?
The second code will create 5 processes, but it will finish after (5*2sec+5*20sec). In the second code why does it go to the else branch?
I'm trying to understand how many processes are created as well as why and how long the code will sleep?
Thanks in advance.
fork will return two times, one in the original process, with the return value of the pid of the child process, the other in the child process, with the return value of zero
DESCRIPTION
fork() creates a new process by duplicating the calling process. The new process is referred to as the child process. The calling process is referred to as the parent process.
and:
RETURN VALUE
On success, the PID of the child process is returned in the parent, and 0 is returned in the child. On failure, -1 is returned in the parent, no child process is created, and errno is set appropriately.
So, after to fork(), you have your newly created process, so you have 2 process, the child (the new process) and the parent (the initial process).
So, what your child (pid == 0) is going into the sleep when you parent (pid > 0) is executing your sleep.
After doing an exec* (execl, execlp, execv, execve, etc...) your process is terminated (try to place a printf or whatever AFTER your execlp, you will see it will never print it (except in case of error (execlp's return value == -1)).
To answer to your initial question:
Yes, your program pass in your if AND in your else (put printf to see clearer), because you have in fact 2 process, and you can even try to put a printf after the else statement, at the very end of your program, and you will see that the child pass (print his pid, it should be equal to 0).

writing in child process c++

I am trying to change a variable value inside a child process and keep it for the rest of the program. So In the below example why my cout keeps printing 0, and how do I solve it?
int var = 0;
int pid = fork();
if (pid == 0){ //child process
var = 1;
exit(1);
}
else if (pid> 0){ //parent process
if (-1 == wait (0))
perror ("there was an error with wait");
}
cout << var;
This is how code execution is going to go.
Child Process
int var =0;
var = 1;
exit (1);
Parent Process
int var =0;
if (-1 == wait (0))
perror ("there was an error with wait);
cout << var;
So as you can see, var will not be changed for the parent process.
When you fork, the child and parent have separate copies of the variables that were present before they split off into execution paths. Processes do not share the same block of memory. Therefore, altering var for the child will not affect the var in the parent.
If you want multiple execution paths on the same piece of memory, you should use threads.
Thank you for reading.
Looks like the fork() call has failed. Check the errno value
RETURN VALUE
On success, the PID of the child process is returned in the parent, and 0 is returned in the child. On failure, -1 is returned in the parent, no child process is created, and errno is set appropriately.
ERRORS
EAGAIN
fork() cannot allocate sufficient memory to copy the parent's page tables and allocate a task structure for the child.
EAGAIN
It was not possible to create a new process because the caller's RLIMIT_NPROC resource limit was encountered. To exceed this limit, the process must have either the CAP_SYS_ADMIN or the CAP_SYS_RESOURCE capability.
ENOMEM
fork() failed to allocate the necessary kernel structures because memory is tight.
CONFORMING TO SVr4, 4.3BSD, POSIX.1-2001.

Issue with fork and wait system call

I have written a basic c++ program in unix with fork() and wait() system call. I am only creating one child. I have used two pipes. So After fork operation with first pipe i am writing from child to parent and as after parent receives the data, parent is writing back to child in second pipe. after that in parent side I am using wait(0) system call. but still my parent process dies before child process?
structure is something like this:
main()
char buff[] = "Parent process kills";
char cuff[] = "before Child process";
int fd1[2];
int fd2[2];
pipe(fd1);
pipe(fd2);
if((pid = fork()) == 0)
{
close(fd1[0]);
close(fd2[1]);
write(fd1[1],buff,strlen(buff)+1);
read(fd2[0],cuff,sizeof(cuff));
}
else
{
close(fd1[1]);
close(fd2[0]);
read(fd1[0],buff,sizeof(buff));
write(fd2[1],cuff,strlen(cuff)+1);
wait((int *) 0);
}
close(fd1);
close(fd2);
}'
Even though wait() is used but still parent process dies before child.
Thanks in adavance.
Your call to read result in undefined behavior. You try to read into string literals, not the buffers you have. In this case it probably results in a crash.
Your write calls also writes a string literal and not the buffer you have.
Also, since you have character arrays initialized to strings, sizeo(buff) and strlen(buff) + 1 are equal.
Are you sure you're not dying due to a segfault? Each of these commands is trying to send more than you intend:
write(fd1[1],"buff",strlen(buff)+1);
and
write(fd2[1],"cuff",strlen(cuff)+1);
and each of these is trying to receive into read-only memory:
read(fd2[0],"cuff",sizeof(cuff));
and
read(fd1[0],"buff",sizeof(buff));
There is a subtle error in the line
if(pid == fork())
You compare the result of fork() with pid instead of assigning to it and comparing it to zero. What you wanted to write is this:
if((pid = fork()))
Note the extra set of parentheses that tells the compiler that you really want to do the assignment, and that you don't want get a warning on it.
And with the corrected if, you have the parent executing the first case, not the second, so the correct code would be:
if(pid == fork()) {
close(fd1[1]);
close(fd2[0]);
read(fd1[0],"buff",sizeof(buff));
write(fd2[1],"cuff",strlen(cuff)+1);
wait((int *) 0);
} else {
close(fd1[0]);
close(fd2[1]);
write(fd1[1],"buff",strlen(buff)+1);
read(fd2[0],"cuff",sizeof(cuff));
}

How do I write a program that tells when my other program ends? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
How do I write a program that tells when my other program ends?
The only way to do a waitpid() or waitid() on a program that isn't spawned by yourself is to become its parent by ptrace'ing it.
Here is an example of how to use ptrace on a posix operating system to temporarily become another processes parent, and then wait until that program exits. As a side effect you can also get the exit code, and the signal that caused that program to exit.:
#include <sys/ptrace.h>
#include <errno.h>
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <sys/wait.h>
int main(int argc, char** argv) {
int pid = atoi(argv[1]);
int status;
siginfo_t si;
switch (ptrace(PTRACE_ATTACH, pid, NULL)) {
case 0:
break;
case -ESRCH:
case -EPERM:
return 0;
default:
fprintf(stderr, "Failed to attach child\n");
return 1;
}
if (pid != wait(&status)) {
fprintf(stderr, "wrong wait signal\n");
return 1;
}
if (!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)) {
/* The pid might not be running */
if (!kill(pid, 0)) {
fprintf(stderr, "SIGSTOP didn't stop child\n");
return 1;
} else {
return 0;
}
}
if (ptrace(PTRACE_CONT, pid, 0, 0)) {
fprintf(stderr, "Failed to restart child\n");
return 1;
}
while (1) {
if (waitid(P_PID, pid, &si, WSTOPPED | WEXITED)) {
// an error occurred.
if (errno == ECHILD)
return 0;
return 1;
}
errno = 0;
if (si.si_code & (CLD_STOPPED | CLD_TRAPPED)) {
/* If the child gets stopped, we have to PTRACE_CONT it
* this will happen when the child has a child that exits.
**/
if (ptrace(PTRACE_CONT, pid, 1, si.si_status)) {
if (errno == ENOSYS) {
/* Wow, we're stuffed. Stop and return */
return 0;
}
}
continue;
}
if (si.si_code & (CLD_EXITED | CLD_KILLED | CLD_DUMPED)) {
return si.si_status;
}
// Fall through to exiting.
return 1;
}
}
On Windows, a technique I've used is to create a global named object (such as a mutex with CreateMutex), and then have the monitoring program open that same named mutex and wait for it (with WaitForSingleObject). As soon as the first program exits, the second program obtains the mutex and knows that the first program exited.
On Unix, a usual way to solve this is to have the first program write its pid (getpid()) to a file. A second program can monitor this pid (using kill(pid, 0)) to see whether the first program is gone yet. This method is subject to race conditions and there are undoubtedly better ways to solve it.
If you want to spawn another process, and then do nothing while it runs, then most higher-level languages already have built-ins for doing this. In Perl, for example, there's both system and backticks for running processes and waiting for them to finish, and modules such as IPC::System::Simple for making it easier to figure how the program terminated, and whether you're happy or sad about that having happened. Using a language feature that handles everything for you is way easier than trying to do it yourself.
If you're on a Unix-flavoured system, then the termination of a process that you've forked will generate a SIGCHLD signal. This means your program can do other things your child process is running.
Catching the SIGCHLD signal varies depending upon your language. In Perl, you set a signal handler like so:
use POSIX qw(:sys_wait_h);
sub child_handler {
while ((my $child = waitpid(-1, WNOHANG)) > 0) {
# We've caught a process dying, its PID is now in $child.
# The exit value and other information is in $?
}
$SIG{CHLD} \&child_handler; # SysV systems clear handlers when called,
# so we need to re-instate it.
}
# This establishes our handler.
$SIG{CHLD} = \&child_handler;
There's almost certainly modules on the CPAN that do a better job than the sample code above. You can use waitpid with a specific process ID (rather than -1 for all), and without WNOHANG if you want to have your program sleep until the other process has completed.
Be aware that while you're inside a signal handler, all sorts of weird things can happen. Another signal may come in (hence we use a while loop, to catch all dead processes), and depending upon your language, you may be part-way through another operation!
If you're using Perl on Windows, then you can use the Win32::Process module to spawn a process, and call ->Wait on the resulting object to wait for it to die. I'm not familiar with all the guts of Win32::Process, but you should be able to wait for a length of 0 (or 1 for a single millisecond) to check to see if a process is dead yet.
In other languages and environments, your mileage may vary. Please make sure that when your other process dies you check to see how it dies. Having a sub-process die because a user killed it usually requires a different response than it exiting because it successfully finished its task.
All the best,
Paul
Are you on Windows ? If so, the following should solve the problem - you need to pass the process ID:
bool WaitForProcessExit( DWORD _dwPID )
{
HANDLE hProc = NULL;
bool bReturn = false;
hProc = OpenProcess(SYNCHRONIZE, FALSE, _dwPID);
if(hProc != NULL)
{
if ( WAIT_OBJECT_0 == WaitForSingleObject(hProc, INFINITE) )
{
bReturn = true;
}
}
CloseHandle(hProc) ;
}
return bReturn;
}
Note: This is a blocking function. If you want non-blocking then you'll need to change the INFINITE to a smaller value and call it in a loop (probably keeping the hProc handle open to avoid reopening on a different process of the same PID).
Also, I've not had time to test this piece of source code, but I lifted it from an app of mine which does work.
Most operating systems its generally the same kind of thing....
you record the process ID of the program in question and just monitor it by querying the actives processes periodically
In windows at least, you can trigger off events to do it...
Umm you can't, this is an impossible task given the nature of it.
Let's say you have a program foo that takes as input another program foo-sub.
Foo {
func Stops(foo_sub) { run foo_sub; return 1; }
}
The problem with this all be it rather simplistic design is that quite simply if foo-sub is a program that never ends, foo itself never ends. There is no way to tell from the outside if foo-sub or foo is what is causing the program to stop and what determines if your program simply takes a century to run?
Essentially this is one of the questions that a computer can't answer. For a more complete overview, Wikipedia has an article on this.
This is called the "halting problem" and is not solvable.
See http://en.wikipedia.org/wiki/Halting_problem
If you want analyze one program without execution than it's unsolvable problem.