Redirection of child process output - c++

I'm redirecting output from a child process:
int pipefd[2];
pipe(pipefd);
pid_t pid = fork(); /* Create a child process */
switch (pid) {
case -1: /* Error */
cout << "Uh-Oh! fork() failed.\n";
exit(1);
case 0: /* Child process */
close(pipefd[0]);
dup2(pipefd[1], 1);
dup2(pipefd[1], 2);
close(pipefd[1]);
execv(args[0], (char * const *)args);
cout << "execv() error" << endl;
exit(1);
default: /* Parent process */
close(pipefd[1]);
char buffer[1024];
size_t bytes_read = 0;
bytes_read = read(pipefd[0], buffer, sizeof(buffer));
if(bytes_read == -1) {
cout << "read() error" << endl;
exit(1);
}
close(pipefd[0]);
if(bytes_read > 0) {
buffer[bytes_read-1] = '\0'; // Overwrite the newline
}
int status, exit_pid;
while(true) {
exit_pid = waitpid(pid, &status, 0);
if(exit_pid == -1) {
cout << "waitpid() error: " << strerror(errno) << endl;
exit(1);
}
else {
return WEXITSTATUS(status);
}
}
}
This works fine when I ran it as an isolated piece of code. But when I integrate it into my multithreaded environment, a horrible thing happens: the read() calls somehow reads output of other threads of the parent process, as if it were the output from the pipe of the child process.
Anyone encountered such a thing?
I'm on OS X.

Well, I have a solution even though I don't completely understand why this happened.
But first, it should be clear that this behavior is neither normal nor expectable. A child process created with fork() does not inherit any running threads from its parent (so the unexpected output must come from the parent threads). And it has its own descriptor table. So when the child process calls dup2() to alter its output descriptors, that shouldn't have any effect on the threads in the parent process.
The problem occurred only in cases where execv() call failed. In those cases, I expected the termination of the child process to close all its file descriptors. But that didn't happen, or at least it didn't have the same effect as calling close() explicitly. So adding explicit close() calls after execv() solved the problem:
execv(args[0], (char * const *)args);
close(1);
close(2);
exit(1);
The close of the write-end descriptor of the pipe is what will cause the read operation on the read-end to receive 0, thus knowing not to read anymore.
However, I still don't know the following:
Why isn't the call to exit() in the child process equivalent to explicitly calling close() ?
Even if the pipe write-end isn't closed, why does reading from the read-end produces output of threads in the parent process, instead of blocking, or returning some error ?
If anybody can shed light on this, it will be appreciated.

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.

Forking and Waiting in linux (C++).

I want to fork a process and then do the following in the parent:
Wait until it terminates naturally or timeout period set by the parent expires (something like waitforsingalobject in windows) after which I will kill the process using kill(pid);
Get the exit code of the child process (assuming it exited naturally)
I need to have access to the std::cout of the child process from the parent.
I attempted to use waitpid() however while this allows me access to the return code I cannot implement a timeout using this function.
I also looked at the following solution (https://www.linuxprogrammingblog.com/code-examples/signal-waiting-sigtimedwait) which allows me to implement a time-out however there doesnt seem a way to get the return code.
I geuss my question boils down to, Whats the correct way achieving this in linux?
You can do #1 and #2 with sigtimedwait function and #3 with pipe:
#include <unistd.h>
#include <signal.h>
#include <iostream>
int main() {
// Block SIGCHLD, so that it only gets delivered while in sigtimedwait.
sigset_t sigset;
sigemptyset(&sigset);
sigaddset(&sigset, SIGCHLD);
sigprocmask(SIG_BLOCK, &sigset, nullptr);
// Make a pipe to communicate with the child process.
int child_stdout[2];
if(pipe(child_stdout))
abort();
std::cout.flush();
std::cerr.flush();
auto child_pid = fork();
if(-1 == child_pid)
abort();
if(!child_pid) { // In the child process.
dup2(child_stdout[1], STDOUT_FILENO); // Redirect stdout into the pipe.
std::cout << "Hello from the child process.\n";
std::cout.flush();
sleep(3);
_exit(3);
}
// In the parent process.
dup2(child_stdout[0], STDIN_FILENO); // Redirect stdin to stdout of the child.
std::string line;
getline(std::cin, line);
std::cout << "Child says: " << line << '\n';
// Wait for the child to terminate or timeout.
timespec timeout = {1, 0};
siginfo_t info;
auto signo = sigtimedwait(&sigset, &info, &timeout);
if(-1 == signo) {
if(EAGAIN == errno) { // Timed out.
std::cout << "Killing child.\n";
kill(child_pid, SIGTERM);
}
else
abort();
}
else { // The child has terminated.
std::cout << "Child process terminated with code " << info.si_status << ".\n";
}
}
Outputs:
Child says: Hello from the child process.
Killing child.
If sleep is commented out:
Child says: Hello from the child process.
Child process terminated with code 3.

Pipe() - read-end in parent process stays empty

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.

Best way to create child process in linux and handle possible failing

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.

Read from unflush binary [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
bash: force exec’d process to have unbuffered stdout
I need to read a binary's (fceux, nes emulator) stdout to get some info, and kill it when I receive special input for a genetic algorithm that I'm trying. So basically, the problem is that the program doesn't flush his output so I receive the output only when the process ends, but it never ends because I'm suppose to kill it.
So is there a way to read from unflushed buffer child ? Even if it is not in C++, so I can add some flush and then read it finally in C++ (but that's becoming a little dirty). I've tried too using python, but didn't find a way to do it either.
Here is a chunk of my code :
int fd[2];
pid_t pid;
pipe (fd);
if ((pid = fork ()) == 0)
{
close (fd[0]);
dup2 (fd[1], STDOUT_FILENO);
execl ("/usr/bin/fceux", "fceux", "Super Mario Bros.zip", NULL)
perror ("fork");
}
else
{
close (fd[1]);
char buf[1];
std::string res;
while (read (fd[0], buf, 1) > 0)
{
std::cout << "Read" << std::endl;
res += buf;
if (res.find ("score") != std::string::npos)
{
std::cout << "KILL" << std::endl;
kill (pid, SIGKILL);
}
}
close (fd[0]);
}
return 0;
Call setbuf(stdout, NULL) just before execl(). It makes stdout unbuffered.