cout/stdout not working after execvp() - c++

So I am attempting to use execvp() from unistd.h in a short program I'm writing. However for some strange reason I seem to be losing the ability to use cout or even printf after calling the execvp function.
For example this works:
pid_t pid;
int status;
if ((pid = fork()) > 0) {
waitpid(pid, &status, 0);
}
else {
execvp(argv[1], &argv[1]);
}
cout << "DONE!" << endl;
But this does not work:
execvp(argv[1], &argv[1]);
cout << "DONE!" << endl;
And, while it is not a huge problem, I would like to understand why it is happening. I have not been able to find anything relevant when I searched here and with Google.
Not sure if this has anything at all to do with the issue but I am using the -std=c++11 flag with g++.

This will not work
execvp(argv[1], &argv[1]);
cout << "DONE!" << endl;
Because the function execvp() never returns (if it succeeded).
It replaces the current processes with a new image and executes that.
On the other this works:
if ((pid = fork()) > 0) {
waitpid(pid, &status, 0);
}
else {
execvp(argv[1], &argv[1]);
}
cout << "DONE!" << endl;
What happens here is that fork() creates a new processes. So you now have two processes at exactly the same place.
One processes has the variable pid set to zero (this is the parent). It goes into the first branch of the if statement and there waits for the child to finish.
One processes has the variable pid set to none zero (this is the child). It goes into the second branch. It executes execvp() which never returns. It does not return because the processes image is replaced by another executable.
Note what you should really do is:
if ((pid = fork()) > 0) {
waitpid(pid, &status, 0);
cout << "Child Finished!" << endl;
}
else {
execvp(argv[1], &argv[1]);
// This code should never execute if everything is OK.
cout << "Child failed to start" << endl;
exit(1);
}

Related

Child Process runs even after parent process has exited?

I was writing a code for a research program. I have following requirement:
1. Main binary execution begins at main()
2. main() fork()
3. child process runs a linpack benchmark binary using execvp()
4. parent process runs some monitoring process and wait for child to exit.
The code is below:
main.cpp
extern ServerUncorePowerState * BeforeStates ;
extern ServerUncorePowerState * AfterStates;
int main(int argc, char *argv[]) {
power pwr;;
procstat st;
membandwidth_t data;
int sec_pause = 1; // sample every 1 second
pid_t child_pid = fork();
if (child_pid >= 0) { //fork successful
if (child_pid == 0) { // child process
int exec_status = execvp(argv[1], argv+1);
if (exec_status) {
std::cerr << "execv failed with error "
<< errno << " "
<< strerror(errno) << std::endl;
}
} else { // parent process
int status = 1;
waitpid(child_pid, &status, WNOHANG);
write_headers();
pwr.init();
st.init();
init_bandwidth();
while (status) {
cout << " Printing status Value: " << status << endl;
sleep (sec_pause);
time_t now;
time(&now);
struct tm *tinfo;
tinfo = localtime(&now);
pwr.loop();
st.loop();
data = getbandwidth();
write_samples(tinfo, pwr, st, data.read_bandwidth + data.write_bandwidth);
waitpid(child_pid, &status, WNOHANG);
}
wait(&status); // wait for child to exit, and store its status
//--------------------This code is not executed------------------------
std::cout << "PARENT: Child's exit code is: "
<< WEXITSTATUS(status)
<< std::endl;
delete[] BeforeStates;
delete[] AfterStates;
}
} else {
std::cerr << "fork failed" << std::endl;
return 1;
}
return 0;
}
What is expected that the child will exit and then parent exits but due to some unknown reason after 16 mins parent exits but child is still running.
Normally It is said that when parent exits the child dies automatically.
What could be the reason for this strange behavior???
Normally It is said that when parent exits the child dies automatically.
Well this is not always true, it depends on the system. When a parent process terminates, the child process is called an orphan process. In a Unix-like OS this is managed by relating the parent process of the orphan process to the init process, this is called re-parenting and it's automatically managed by the OS. In other types of OS, orphan processes are automatically killed by the system. You can find more details here.
From the code snippet I would think that maybe the issue is in the wait(&status) statement. The previous loop would end (or not be executed) when the return status is 0, which is the default return value from your final return 0 at the end, that could be yielded by the previous waitpid(child_pid, &status, WNOHANG) statements. This means that the wait(&status) statement would wait on a already terminated process, this may cause some issues.

fork() and waitpid() not waiting for child

I am having a bit of trouble getting waitpid to work could someone please explain what is wrong with this code?
#include <iostream>
#include <sys/wait.h>
#include <unistd.h>
using namespace std;
int main() {
string filename_memory;
decltype(fork()) pid;
if (!(pid = fork())) {
cout << "in child" << endl;
sleep(1);
}
else {
int status_child;
do {
waitpid(pid, &status_child, WNOHANG);
cout << "waiting for child to finish" << endl;
} while (!WIFEXITED(status_child));
cout << "child finished" << endl;
}
return 0;
}
If wait() or waitpid() returns because the status of a child process
is available, these functions shall return a value equal to the
process ID of the child process for which status is reported.
If waitpid() was invoked with WNOHANG set in options, it has at least
one child process specified by pid for which status is not available,
and status is not available for any process specified by pid, 0 is
returned. Otherwise, (pid_t)-1 shall be returned, and errno set to
indicate the error.
This means that the status_child variable has no meaning until waitpid returns the pid of the child.
You can fix this by applying these changes:
int ret;
do {
ret = waitpid(pid, &status_child, WNOHANG);
cout << "waiting for child to finish" << endl;
} while (ret != pid || !WIFEXITED(status_child));
cout << "child finished" << endl;

Fork child and parent running separate code

I'm trying to dot product two vectors, with each process taking on a separate starting and ending index. What seems to be happening is that the code gets executed twice.
void DotProduct::MultiProcessDot()
{
pid_t pID,w;
int status;
unsigned int index = mNumberOfValuesPerVector / 2;
if((pID = fork()) < 0){
cout << "fork error" << endl;
}
else if(pID == 0){ /* child */
ProcessDotOperation(0, index);
exit(EXIT_FAILURE);
}
else{ /* parent */
ProcessDotOperation(index, mNumberOfValuesPerVector);
w = waitpid(pID, &status, WNOHANG);
if(w == 0){
cout << "alive" << endl;
}else if(w == -1){
cout << "dead" << endl;
}
}
}
ProcessDotOperation calculates the dot product using shared memory with sem_wait() and sem_post(). What seems to be happening is this:
Parent runs ProcessDotOperation
"alive" is printed
Parent runs ProcessDotOperation
"alive" is printed
Program continues execution (going on to other functions)
Child runs ProcessDotOperation
Child runs ProcessDotOperation
Note: I may have a fundamental misunderstanding of what's happening, so by parent and child, I'm referring to the comments in the code as to which process I think is running.
How do I make it such that the child runs ProcessDotOperation once, the parent runs ProcessDotOperation once, and then the program continues operation?
Any help is appreciated.
Edit
If I print before the fork(), and change w = waitpid(pID, &status, WNOHANG); to w = waitpid(pID, &status, 0);, here's the output:
forking
parent
child
forking
parent
child
continued execution...
Here's the code of ProcessDotOperation:
void DotProduct::ProcessDotOperation(unsigned int startIndex, unsigned int endIndex)
{
for(unsigned int i = startIndex; i < endIndex; i++){
sem_wait(mSem);
mShmProductId += mVectors[0][i] * mVectors[1][i];
cout << startIndex << " " << endIndex << " " << i << endl;
sem_post(mSem);
}
}
Someone is calling MultiProcessDot a second time.
I think you need a loop around the waitpid(). As it is written, you wait once, without hanging around for a dead child, returning immediately if the child is not yet dead. This allows the parent to go on with other activities, of course.
I'm not sure it's a complete explanation of what you observe, but we can't see your trace code. Print things like the process's PID with each message.

Fork(): Dont return from child until it's terminated

I'm having some troubles with fork() and that kind of things.
I'm developing a shell, where the user can write commands that whill be executed as in a normal and common shell.
I have a main function like this:
void Shell::init() {
string command;
while (1) {
cout << getPrompt() << " ";
command = readCommand();
if (command.length() > 0) handleCommand(command);
}
}
handleCommand() is the function that does pretty much everything. Somewhere in it, I have the following:
...
else {
pid_t pid;
pid = fork();
char* arg[tokens.size() + 1];
for (int i = 0; i < tokens.size(); ++i) {
arg[i] = (char*) tokens[i].c_str();
}
arg[tokens.size()] = NULL;
if (pid == 0) {
if (execvp(tokens[0].c_str(), arg) == -1) {
cout << "Command not known. " << endl;
};
} else {
wait();
}
}
What I want is that when I reach that point, the command will be treated as a program invocation, so I create a child to run it. It's working almost perfect, but I get the prompt again before the program output. Example:
tronfi#orion:~/NetBeansProjects/Shell2$ whoami
tronfi#orion:~/NetBeansProjects/Shell2$ tronfi
tronfi#orion:~/NetBeansProjects/Shell2$
The child should die after the execvp, so it shouldn't be calling the prompt, and the parent is waiting until the child die.
So... what I'm doing wrong?
Thanks!!
You are calling wait() incorrectly. It expects to be passed a pointer-to-int, in which the child's exit status will be stored:
int status;
wait(&status);
Really, though, you should be using waitpid() to check for the specific child that you're after. You also need to loop around if waitpid() is interrupted by a signal:
int r;
do {
r = waitpid(pid, &status, 0);
} while (r < 0 && errno == EINTR);
I'm not sure that this is exactly the problem, but you must ensure that the child exits even if execvp() fails:
if (pid == 0) {
if (execvp(tokens[0].c_str(), arg) == -1) {
cout << "Command not known. " << endl;
};
exit(1); // or some other error code to indicate execvp() fails
} else {
wait();
}
If you don't do this, then if excecvp() fails then you will end up with two instances of your shell, which is probably not what you want.
The child must be terminated using the call exit(0) (only on success), as this helps in clening of memory and flushes the buffer. This status returned by the child must be checked by the parent and then only it should give the prompt.
Let me know if you need more details.

How to wait until all child processes called by fork() complete?

I am forking a number of processes and I want to measure how long it takes to complete the whole task, that is when all processes forked are completed. Please advise how to make the parent process wait until all child processes are terminated? I want to make sure that I stop the timer at the right moment.
Here is as a code I use:
#include <iostream>
#include <string>
#include <fstream>
#include <sys/time.h>
#include <sys/wait.h>
using namespace std;
struct timeval first, second, lapsed;
struct timezone tzp;
int main(int argc, char* argv[])// query, file, num. of processes.
{
int pCount = 5; // process count
gettimeofday (&first, &tzp); //start time
pid_t* pID = new pid_t[pCount];
for(int indexOfProcess=0; indexOfProcess<pCount; indexOfProcess++)
{
pID[indexOfProcess]= fork();
if (pID[indexOfProcess] == 0) // child
{
// code only executed by child process
// magic here
// The End
exit(0);
}
else if (pID[indexOfProcess] < 0) // failed to fork
{
cerr << "Failed to fork" << endl;
exit(1);
}
else // parent
{
// if(indexOfProcess==pCount-1) and a loop with waitpid??
gettimeofday (&second, &tzp); //stop time
if (first.tv_usec > second.tv_usec)
{
second.tv_usec += 1000000;
second.tv_sec--;
}
lapsed.tv_usec = second.tv_usec - first.tv_usec;
lapsed.tv_sec = second.tv_sec - first.tv_sec;
cout << "Job performed in " <<lapsed.tv_sec << " sec and " << lapsed.tv_usec << " usec"<< endl << endl;
}
}//for
}//main
I'd move everything after the line "else //parent" down, outside the for loop. After the loop of forks, do another for loop with waitpid, then stop the clock and do the rest:
for (int i = 0; i < pidCount; ++i) {
int status;
while (-1 == waitpid(pids[i], &status, 0));
if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
cerr << "Process " << i << " (pid " << pids[i] << ") failed" << endl;
exit(1);
}
}
gettimeofday (&second, &tzp); //stop time
I've assumed that if the child process fails to exit normally with a status of 0, then it didn't complete its work, and therefore the test has failed to produce valid timing data. Obviously if the child processes are supposed to be killed by signals, or exit non-0 return statuses, then you'll have to change the error check accordingly.
An alternative using wait:
while (true) {
int status;
pid_t done = wait(&status);
if (done == -1) {
if (errno == ECHILD) break; // no more child processes
} else {
if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
cerr << "pid " << done << " failed" << endl;
exit(1);
}
}
}
This one doesn't tell you which process in sequence failed, but if you care then you can add code to look it up in the pids array and get back the index.
The simplest method is to do
while(wait() > 0) { /* no-op */ ; }
This will not work if wait() fails for some reason other than the fact that there are no children left. So with some error checking, this becomes
int status;
[...]
do {
status = wait();
if(status == -1 && errno != ECHILD) {
perror("Error during wait()");
abort();
}
} while (status > 0);
See also the manual page wait(2).
Call wait (or waitpid) in a loop until all children are accounted for.
In this case, all processes are synchronizing anyway, but in general wait is preferred when more work can be done (eg worker process pool), since it will return when the first available process state changes.
I believe the wait system call will accomplish what you are looking for.
for (int i = 0; i < pidCount; i++) {
while (waitpid(pids[i], NULL, 0) > 0);
}
It won't wait in the right order, but it will stop shortly after the last child dies.