I've been tasked to create a program that takes a text file that contains a list of programs as input. It then needs to run valgrind on the programs (one at a time) until valgrind ends or until the program hits a max allotted time. I have the program doing everything I need it to do EXCEPT it isn't waiting for valgrind to finish. The code I'm using has this format:
//code up to this point is working properly
pid_t pid = fork();
if(pid == 0){
string s = "sudo valgrind --*options omitted*" + testPath + " &>" + outPath;
system(s.c_str());
exit(0);
}
//code after here seems to also be working properly
I'm running into an issue where the child just calls the system and moves on without waiting for valgrind to finish. As such I'm guessing that system isn't the right call to use, but I don't know what call I should be making. Can anyone tell me how to get the child to wait for valgrind to finish?
I think that you are looking for fork/execv. Here is an example:
http://www.cs.ecu.edu/karl/4630/spr01/example1.html
An other alternative could be popen.
You can fork and exec your program and then wait for it to finish. See the following example.
pid_t pid = vfork();
if(pid == -1)
{
perror("fork() failed");
return -1;
}
else if(pid == 0)
{
char *args[] = {"/bin/sleep", "5", (char *)0};
execv("/bin/sleep", args);
}
int child_status;
int child_pid = wait(&child_status);
printf("Child %u finished with status %d\n", child_pid, child_status);
Related
I want to get the pid of some process(let's call it Somebinary) which is started with the help of exec family inside child process and assume Somebinary never stops once started. I want to print the pid of this process from the parent process.
I can't wait in the parent process as the child process will start Somebinary through exec* and that will never stop. I know I can do:
int start(std::string Somebinary){
pid_t childpid = fork();
if(childpid == 0){
freopen(logfile.c_str(), "a+", stdout);
dup2(1, 2);
exec*("/bin/sh", "sh", "-c", Somebinary.c_str(), " &", NULL)
exit(1);
}
// print pid of Somebinary from here
return 0;
}
but I want to reduce extra overhead if possible.
Basically, I want to do the following thing as we do in bash from C/C++:
Bash
$ Somebinary > logfile 2>&1 &
$ pidof Somebinary
I know I can do stdout and stderr redirects with the help of freopen and dup2 in the child process. But the rest is the doubt.
P.S.: this has to be done in Linux
Thanks a lot for the help.
Note that exec does not "create a process" or change the PID, fork does.
As #kaylum said, childpid is the PID of the exec'd process already. You can just print it:
int start(std::string Somebinary){
pid_t childpid = fork();
if(childpid == 0){
freopen(logfile.c_str(), "a+", stdout);
dup2(1, 2);
exec(Somebinary.c_str(), NULL);
exit(1);
}
if (childpid < 0) { // basic error handling
perror("fork"); return -1;
}
// print pid of Somebinary from here
printf("childpid = %jd\n", (intmax_t) childpid);
return 0;
}
Also you might want to bypass /bin/sh and exec the Somebinary directly, otherwise you'll get the PID of /bin/sh.
This is the code for playing sound file in C++ linux code
string str1 = "aplay ";
str1 = str1 + " out.wav" + " & ";
const char *command = str1.c_str();
system(command);
** Entire code is available here : Playing sound C++ linux aplay : device or resource busy
I just want to know how to play this in a fork() as I read that system call is too taxing on cpu, which ofcourse is in my case.
Please help
fork will make a copy of your process, so you can easily write:
// fork the current process: beyond this point, you will have 2 process
int ret = fork();
if (ret == 0) {
// in child: execute the long command
system("aplay out.wav");
// exit the child process
exit(0);
}
// child process will not go here
if (ret < 0) {
perror("fork");
}
After, you should know that system will do for you fork + exec + wait. Since you don't want your parent process to wait the child, you can write:
// fork the current process: beyond this point, you will have 2 process
int ret = fork();
if (ret == 0) {
// in child: execute the long command
char program[] = "/usr/bin/aplay";
char *args[] = {"/usr/bin/aplay", "out.wav" };
ret = execv(program, args);
// this point will be reach only if `exec` fails
// so if we reach this point, we've got an error.
perror("execv");
exit(0);
}
// child process will not go here
if (ret < 0) {
perror("fork");
}
I am new to fork and exec, and I tried the following program.
Program 1:
int main(int argc, char *argv[]){
pid_t pid;
int status;
pid = fork();
if(pid == 0){
printf("new process");
execv("p1",argv);
}
else{
pid_t pr = wait(&status);// I am trying to get the exit value
// of the sub process.
printf("the child process exit with %d",status);
printf("father still running\n");
}
}
Program 2:
int main(){
std::cout<<"I am the new thread"<<std::endl;
sleep(1);
std::cout<<"after 1 second"<<std::endl;
exit(1);
}
I run the first program, and the output is "the child process exit with 256". Why is the result 256 instead of 1? If I change exit(1) to exit(2), the result becomes 512, why is that? It only worked if I return 0.
The status value you get back from the wait system call is not necessarily what your child process exited with.
There are a number of other pieces of information that can be returned as well, such as:
did the process terminate normally?
was it terminated by a signal?
what was the signal that terminated it?
did it dump core?
In order to extract the exit code, you use a macro:
WEXITSTATUS(status)
That, and the macros that can give you more information, should be available on the wait man-page, such as the one here.
When we use system() command, program wait until it complete but I am executing a process using system() and using load balance server due to which program comes to next line just after executing system command. Please note that that process may not be complete.
system("./my_script");
// after this I want to see whether it is complete or not using its pid.
// But how do i Know PID?
IsScriptExecutionComplete();
Simple answer: you can't.
The purpose of system() is to block when command is being executed.
But you can 'cheat' like this:
pid_t system2(const char * command, int * infp, int * outfp)
{
int p_stdin[2];
int p_stdout[2];
pid_t pid;
if (pipe(p_stdin) == -1)
return -1;
if (pipe(p_stdout) == -1) {
close(p_stdin[0]);
close(p_stdin[1]);
return -1;
}
pid = fork();
if (pid < 0) {
close(p_stdin[0]);
close(p_stdin[1]);
close(p_stdout[0]);
close(p_stdout[1]);
return pid;
} else if (pid == 0) {
close(p_stdin[1]);
dup2(p_stdin[0], 0);
close(p_stdout[0]);
dup2(p_stdout[1], 1);
dup2(::open("/dev/null", O_RDONLY), 2);
/// Close all other descriptors for the safety sake.
for (int i = 3; i < 4096; ++i)
::close(i);
setsid();
execl("/bin/sh", "sh", "-c", command, NULL);
_exit(1);
}
close(p_stdin[0]);
close(p_stdout[1]);
if (infp == NULL) {
close(p_stdin[1]);
} else {
*infp = p_stdin[1];
}
if (outfp == NULL) {
close(p_stdout[0]);
} else {
*outfp = p_stdout[0];
}
return pid;
}
Here you can have not only PID of the process, but also it's STDIN and STDOUT. Have fun!
Not an expert on this myself, but if you look at the man page for system:
system() executes a command specified in command by calling /bin/sh -c command, and returns after the command has been completed
You can go into the background within the command/script you're executing (and return immediately), but I don't think there's a specific provision in system for that case.
Ideas I can think of are:
Your command might return the pid through the return code.
Your code might want to look up the name of the command in the active processes (e.g. /proc APIs in unix-like environments).
You might want to launch the command yourself (instead of through a SHELL) using fork/exec
As the other answers said, std::system blocks until complete anyway. However, if you want to run the child process async and you are ok with boost you can use boost.process (ref):
#include <boost/process.hpp>
namespace bp = boost::process;
bp::child c(bp::search_path("echo"), "hello world");
std::cout << c.id() << std::endl;
// ... do something with ID ...
c.wait();
You can check exit status of your command by following code :
int ret = system("./my_script");
if (WIFEXITED(ret) && !WEXITSTATUS(ret))
{
printf("Completed successfully\n"); ///successful
}
else
{
printf("execution failed\n"); //error
}
I have the helper function below, used to execute a command and get the return value on posix systems. I used to use popen, but it is impossible to get the return code of an application with popen if it runs and exits before popen/pclose gets a chance to do its work.
The following helper function creates a process fork, uses execvp to run the desired external process, and then the parent uses waitpid to get the return code. I'm seeing odd cases where it's refusing to run.
When called with wait = true, waitpid should return the exit code of the application no matter what. However, I'm seeing stdout output that specifies the return code should be non-zero, yet the return code is zero. Testing the external process in a regular shell, then echoing $? returns non-zero, so it's not a problem w/ the external process not returning the right code. If it's of any help, the external process being run is mount(8) (yes, I know I can use mount(2) but that's besides the point).
I apologize in advance for a code dump. Most of it is debugging/logging:
inline int ForkAndRun(const std::string &command, const std::vector<std::string> &args, bool wait = false, std::string *output = NULL)
{
std::string debug;
std::vector<char*> argv;
for(size_t i = 0; i < args.size(); ++i)
{
argv.push_back(const_cast<char*>(args[i].c_str()));
debug += "\"";
debug += args[i];
debug += "\" ";
}
argv.push_back((char*)NULL);
neosmart::logger.Debug("Executing %s", debug.c_str());
int pipefd[2];
if (pipe(pipefd) != 0)
{
neosmart::logger.Error("Failed to create pipe descriptor when trying to launch %s", debug.c_str());
return EXIT_FAILURE;
}
pid_t pid = fork();
if (pid == 0)
{
close(pipefd[STDIN_FILENO]); //child isn't going to be reading
dup2(pipefd[STDOUT_FILENO], STDOUT_FILENO);
close(pipefd[STDOUT_FILENO]); //now that it's been dup2'd
dup2(pipefd[STDOUT_FILENO], STDERR_FILENO);
if (execvp(command.c_str(), &argv[0]) != 0)
{
exit(EXIT_FAILURE);
}
return 0;
}
else if (pid < 0)
{
neosmart::logger.Error("Failed to fork when trying to launch %s", debug.c_str());
return EXIT_FAILURE;
}
else
{
close(pipefd[STDOUT_FILENO]);
int exitCode = 0;
if (wait)
{
waitpid(pid, &exitCode, wait ? __WALL : (WNOHANG | WUNTRACED));
std::string result;
char buffer[128];
ssize_t bytesRead;
while ((bytesRead = read(pipefd[STDIN_FILENO], buffer, sizeof(buffer)-1)) != 0)
{
buffer[bytesRead] = '\0';
result += buffer;
}
if (wait)
{
if ((WIFEXITED(exitCode)) == 0)
{
neosmart::logger.Error("Failed to run command %s", debug.c_str());
neosmart::logger.Info("Output:\n%s", result.c_str());
}
else
{
neosmart::logger.Debug("Output:\n%s", result.c_str());
exitCode = WEXITSTATUS(exitCode);
if (exitCode != 0)
{
neosmart::logger.Info("Return code %d", (exitCode));
}
}
}
if (output)
{
result.swap(*output);
}
}
close(pipefd[STDIN_FILENO]);
return exitCode;
}
}
Note that the command is run OK with the correct parameters, the function proceeds without any problems, and WIFEXITED returns TRUE. However, WEXITSTATUS returns 0, when it should be returning something else.
Probably isn't your main issue, but I think I see a small problem. In your child process, you have...
dup2(pipefd[STDOUT_FILENO], STDOUT_FILENO);
close(pipefd[STDOUT_FILENO]); //now that it's been dup2'd
dup2(pipefd[STDOUT_FILENO], STDERR_FILENO); //but wait, this pipe is closed!
But I think what you want is:
dup2(pipefd[STDOUT_FILENO], STDOUT_FILENO);
dup2(pipefd[STDOUT_FILENO], STDERR_FILENO);
close(pipefd[STDOUT_FILENO]); //now that it's been dup2'd for both, can close
I don't have much experience with forks and pipes in Linux, but I did write a similar function pretty recently. You can take a look at the code to compare, if you'd like. I know that my function works.
execAndRedirect.cpp
I'm using the mongoose library, and grepping my code for SIGCHLD revealed that using mg_start from mongoose results in setting SIGCHLD to SIG_IGN.
From the waitpid man page, on Linux a SIGCHLD set to SIG_IGN will not create a zombie process, so waitpid will fail if the process has already successfully run and exited - but will run OK if it hasn't yet. This was the cause of the sporadic failure of my code.
Simply re-setting SIGCHLD after calling mg_start to a void function that does absolutely nothing was enough to keep the zombie records from being immediately erased.
Per #Geoff_Montee's advice, there was a bug in my redirect of STDERR, but this was not responsible for the problem as execvp does not store the return value in STDERR or even STDOUT, but rather in the kernel object associated with the parent process (the zombie record).
#jilles' warning about non-contiguity of vector in C++ does not apply for C++03 and up (only valid for C++98, though in practice, most C++98 compilers did use contiguous storage, anyway) and was not related to this issue. However, the advice on reading from the pipe before blocking and checking the output of waitpid is spot-on.
I've found that pclose does NOT block and wait for the process to end, contrary to the documentation (this is on CentOS 6). I've found that I need to call pclose and then call waitpid(pid,&status,0); to get the true return value.