I've got a function for starting a process, and then returning the stdout and exit code. However I've noticed that it claims that every process returns the exit code of 1. I control the executable being invoked and I had it print to stdout the exit code, so I've confirmed that when it "failed", it in fact returned 0 from main. I also invoked the executable directly form the shell and confirmed the expected stdout and exit code (0). So the fault must lie on the side of the caller. I've also confirmed that WIFEXITED doesn't return false- it returns true as if the child had exited normally (which it did).
This code worked fine before I needed to capture stdout, so it must have something to do with that. I tried looking into the "Child has already terminated" jobby, but that's not occurring in this case- waitpid() behaves exactly like I'd expect and just doesn't care that the child might have already terminated whilst I was nomming up the stdout.
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <iostream>
Wide::Driver::ProcessResult Wide::Driver::StartAndWaitForProcess(std::string name, std::vector<std::string> args, Util::optional<unsigned> timeout) {
int filedes[2];
pipe(filedes);
pid_t pid = fork();
if (pid == 0) {
while ((dup2(filedes[1], STDOUT_FILENO) == -1) && (errno == EINTR)) {}
freopen("/dev/null", "rw", stdin);
freopen("/dev/null", "rw", stderr);
//close(filedes[0]);
std::vector<const char*> cargs;
cargs.push_back(name.c_str());
for (auto&& arg : args)
cargs.push_back(arg.c_str());
cargs.push_back(nullptr);
execv(name.c_str(), const_cast<char* const*>(&cargs[0]));
}
std::string std_out;
close(filedes[1]);
char buffer[4096];
while (1) {
ssize_t count = read(filedes[0], buffer, sizeof(buffer));
if (count == -1) {
if (errno == EINTR) {
continue;
} else {
perror("read");
exit(1);
}
} else if (count == 0) {
break;
} else {
std_out += std::string(buffer, buffer + count);
}
}
close(filedes[0]);
int status;
ProcessResult result;
result.std_out = std_out;
waitpid(pid, &status, 0);
if (!WIFEXITED(status))
result.exitcode = 1;
else {
result.exitcode = WEXITSTATUS(status);
if (result.exitcode != 0) {
std::cout << name << " failed with code " << result.exitcode << "\n";
std::cout << "stdout: " << result.std_out;
}
}
return result;
}
Why on earth is waitpid() giving me this strange result and how can I fix it?
I've confirmed in IRC that it is an LLVM issue. The exit code for the process I printed out is what I returned from main- a static destructor or other such code can still run and call exit(1). This is caused by redirecting stderr- so basically you can't get the error, since if you don't redirect stderr you don't see the problem. So if you execute from the shell, since stderr is not redirected, it's all good.
Therefore, despite the shell and my own return code agreeing, the process was in fact returning the exit code of 1.
Apparently the issue is resolved in trunk, or should be, but I am still using 3.6.
Related
if everything is not perfect I apologize;)
I am doing a program in c ++ that when it receives a sensor information, shows a picture with feh full screen.
The problem is that when I want to go from one image to another, It opens a new feh, until the moment when the computer crashes because it takes all the memory ...
How to make the opening of an image close the previous one?
This is my current command line :
system("feh -F ressources/icon_communication.png&");
I must specify that I also trigger a sound, but that there is no problem because the program closes automatically at the end of the sound:
system("paplay /home/pi/demo_ecran_interactif/ressources/swip.wav&");
Tried this as a test and works ! Thanks #paul-sanders !
#include <iostream>
#include <chrono>
#include <thread>
#include <unistd.h>
#include <signal.h>
using namespace std;
pid_t display_image_file (const char *image_file)
{
pid_t pid = fork ();
if (pid == -1)
{
std::cout << "Could not fork, error: " << errno << "\n";
return -1;
}
if (pid != 0) // parent
return pid;
// child
execlp ("feh", "-F", image_file, NULL); // only returns on failure
std::cout << "Couldn't exec feh for image file " << image_file << ", error: " << errno << "\n";
return -1;
}
int main()
{
pid_t pid = display_image_file ("nav.png");
if (pid != -1)
{
std::this_thread::sleep_for (std::chrono::milliseconds (2000));
kill (pid, SIGKILL);
}
pid_t pid2 = display_image_file ("sms2.png");
}
Soooooooooo, the goal here (in terms of your test program) seems to be:
display nav.png in feh
wait 2 seconds
close (that instance of) feh
display sms2.png in feh
And if you can get the test program doing that then you will be on your way (I'm not going to worry my pretty little head about your sound issue (because it's 30+ degrees here today), but once you have your test program running right then you will probably be able to figure out how to solve that one yourself).
So, two issues that I see in your code here:
you're not making any effort to close the first instance of 'feh'
execlp() doesn't do quite what you probably think it does (specifically, it never returns, unless it fails for some reason).
So what I think you need to do is something like this (code untested, might not even compile and you need to figure out the right header files to #include, but it should at least get you going):
pid_t display_image_file (const char *image_file)
{
pid_t pid = fork ();
if (pid == -1)
{
std::cout << "Could not fork, error: " << errno << "\n";
return -1;
}
if (pid != 0) // parent
return pid;
// child
execlp ("feh", "-F", image_file, NULL); // only returns on failure
std::cout << "Couldn't exec feh for image file " << image_file << ", error: " << errno << "\n";
return -1;
}
int main()
{
pid_t pid = display_image_file ("nav.png");
if (pid != -1)
{
std::this_thread::sleep_for (std::chrono::milliseconds (2000));
kill (pid, SIGKILL);
}
pid_t pid = display_image_file ("sms2.png");
// ...
}
Does that help?
This question follows from my attempts to implement
http://www.microhowto.info/howto/capture_the_output_of_a_child_process_in_c.html
and
https://linux.die.net/man/2/pipe
I'm writing a shell program; the intention is that, eventually, it can execute commands and pipe them to another program. As such, I require the stdout of a child process directly, rather than outputting to terminal. I attempted to use the above guides, but I have a problem: The pipe is always empty. It just doesn't work. I have absolutely no clue why. Here's my code:
int pipefd[2];
pid_t pid;
pid = fork();
char buf;
const char* arg = "/bin/ls";
char *args[] = {"/bin/ls", (char *) 0};
if (pipe(pipefd) == -1) {
perror("pipe");
exit(EXIT_FAILURE);
}
if(pid<0) {
std::cout << "Fork() failed!." << std::endl;
exit(EXIT_FAILURE);
} else if (pid == 0) { //According to everything I could find on the internet, pipe should work.
dup2(pipefd[1], STDOUT_FILENO); // It does not. I don't know why.
close(pipefd[1]);
close(pipefd[0]);
execv(arg, args);
std::cout << "Child Error! " << errno << std::endl;
perror("execv");
exit(EXIT_FAILURE);
} else {
close(pipefd[1]);
wait(NULL);
while (read(pipefd[0], &buf, 1) > 0){
write(STDOUT_FILENO, &buf, 1);
}
write(STDOUT_FILENO, "\n", 1);
close(pipefd[0]);
}
I'm on a laptop with Ubuntu 15.04
Also, the pipe DOES work if I write/read inside one process.
Edit: Also, the execv does work - If I remove the dup2, it outputs directly to terminal and works.
I am running this basic shell program in another shell. I am unable to figure out why my shell doesn't keep running after "ls" executes. I dont have an exit for it but it goes back to original shell. I have to run my shell program every time if want to use it. i figured thats what the fork() is supposed to do. I only want my shell to exit using the exit command which i coded with the if else statement. Any suggestions would be much appreciated. Oh and disregard the gettoks() parser function, i couldn't figure out how to use it for input so i wrote if else statements for the string input cmSTR rather then using the gettoks() parser. Mainly because i couldn't figure how to pass the input into it
#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <errno.h>
#include <signal.h>
#include <cstdlib>
#include <sys/wait.h>
using namespace std;
// Initializing counters for trapping
static int cc_counter = 0;
static int cz_counter = 0;
static int cq_counter = 0;
//Functions for trap signal handler
void cc_handler( int signo )
{
++cc_counter;
}
void cz_handler( int signo )
{
++cz_counter;
}
void cq_handler( int signo )
{
++cq_counter;
}
//*********************************************************
//
// Extern Declarations
//
//*********************************************************
using namespace std;
extern "C"
{
extern char **gettoks();
}
//*********************************************************
//
// Main Function
//
//*********************************************************
int main( int argc, char *argv[] )
{
// local variables
int ii;
char **toks;
int retval;
// initialize local variables
ii = 0;
toks = NULL;
retval = 0;
char buf[1000];//Initialize of size for current working directory
string cmSTR;//String to hold input
int status;//Initialization of status for fork()
pid_t pid;//Declaration of pid
// main (infinite) loop
while( true )
{
signal( SIGINT, cc_handler );// Traps Ctrl+C
signal( SIGTSTP, cz_handler);// Traps Ctrl+Z
signal( SIGQUIT, cq_handler);// Traps Ctrl+\
//prompt and show current working directory
cout <<("RS_SHELL:") << getcwd(buf,1000) << "\t";
getline(cin ,cmSTR);//read input from keyboard
// if else loop to switch based on command input
if(cmSTR == "ls")// if ls, then execute arguement
{
execl( "/bin/ls", "ls", NULL );//System call to execute ls
}
else if(cmSTR == "exit")//if exit, then execute block of code
{
cout << "Ctrl C entered: " << ++cc_counter << "times"<< endl;
cout << "Ctrl Z entered: " << ++cz_counter << "times"<< endl;
cout << "Ctrl Back Slash entered: " << ++cq_counter << "times"<< endl;
exit(1);
}
else if(cmSTR == "guish")// if guish, execute guish shell
{
execvp("guish", NULL);
}
//if input is not any of previous commands then fork()
else if(cmSTR != "ls" && cmSTR != "exit" && cmSTR != "guish" && cmSTR != "\n")
{
pid = fork();
if (pid < 0)//Loop to fork parent and child process
{
fprintf(stderr, "Fork Failed");
exit(-1);
}
else if (pid == 0)//Child process
{
execvp("guish", NULL);//system call to execute guish shell
}
else //Parent process
{
waitpid( -1, &status,0);
exit(0);
}
}
// get arguments
toks = gettoks();
if( toks[0] != NULL )
{
// simple loop to echo all arguments
for( ii=0; toks[ii] != NULL; ii++ )
{
cout << "Argument " << ii << ": " << toks[ii] << endl;
}
if( !strcmp( toks[0], "exit" ))
break;
}
}
// return to calling environment
return( retval );
}
As you suspected, execl and its related functions overlay the current process with a new process. Thus, after the execl call that starts ls, your program won't exist any more to keep running.
If you want your shell program to stay around after running ls, you'll need to fork() before the call execl( "/bin/ls", "ls", NULL );.
Also, if you want the output from ls to appear in the same console as your shell, as I think you might be intending, you will need to pipe the output from ls back to your shell and then write that output onto your shell's console. See Writing my own shell… stuck on pipes?, for instance.
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.