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.
Related
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.
I have parent process, that have to create few children processes. Best way I found is using fork + execl. But then parent process need to know if execl of concrete child fails or not, and I don't know how to implement that.
int pid = fork();
if (pid < 0) {
std::cout << "ERROR on fork." << std::endl;
} if (pid == 0) {
execl("/my/program/full/path", (char *)NULL);
exit(1);
}
else {
if (/*child's process execl fails*/) {
std::cout << "it failed" << std::endl
} else {
std::cout << "child born" << std::endl
}
}
I think this idea is not good:
int status(0);
sleep(100);
int res = waitpid(pid, &status, WNOHANG);
if (res < 0 && errno == 10) {
std::cout << "it failed" << std::endl
} else {
std::cout << "child born" << std::endl
}
because it's not good to hope that child process will die after 100 milliseconds, I want to know that for sure as only that will happens.
I also think that creation of shared_memory or special pipe connection for such check is a Cannon against Bees.
There have to be simple solution for that, that I just didn't found yet.
What is the best way to achieve that?
As a general solution you can register signal handler (SIGUSR1) in the parent using sigaction().
In a child: unregister signal handler, if execl() call failed you need to send SIGUSR1 to the parent.
In the parent: Every child pid we will store in std::set. When all childs are created you just create a separate thread for tracking childs. In the thread function just call wait() and remove pid from the set. Another way to listen SIGCHLD signal (but it will lead to more complex solution, so if spawn another thread is an option I'd use thread).
When the set is empty we have done.
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);
}
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.
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.