I am spent whole half a day, but still couldn't figure, why is the dash being launched with execl
call just becomes a zombie.
Below is a minimal test case — I'm just fork a child, make a duplicate of std [in,out,err] descriptors, and launch the sh.
#include <cstdio>
#include <fcntl.h>
#include <cstring>
#include <stdlib.h>
#include <cerrno>
#include <unistd.h>
int main() {
int pipefd[2];
enum {
STDOUT_TERM = 0,
STDIN_TERM = 1
};
if (pipe(pipefd) == -1) { //make a pipe
perror("pipe");
return 0;
}
pid_t pid = fork();
if (pid == 0)
{// Child
dup2(pipefd[STDIN_TERM], STDIN_FILENO);
dup2(pipefd[STDOUT_TERM], STDOUT_FILENO);
dup2(pipefd[STDOUT_TERM], STDERR_FILENO);
execl("/bin/sh","sh", (char*)NULL);
// Nothing below this line should be executed by child process. If so, print err
perror("For creating a shell process");
exit(1);
}
__asm("int3");
puts("Child launched");
}
When I launch it in a debugger, and at the line with breakpoint (above the puts()
call) look at the pid variable, and then look at the according process with ps, I every time getting something like
2794 pts/10 00:00:00 sh <defunct>
I.e. its a zombie
pipe
afterfork
) then don't use the pipe at all in the parent. In the child, youdup2
the pipe to stdio, with the apparent net effect that you loop the child's stdout back to its own stdin! Moving on, I have no clue what__asm("int3")
is supposed to do. This is architecture-specific voodoo? Can you do without that?execl
is dying (might be related to the bizarre stdio loop) but you aren't waiting for it in the parent, so that would probably be why the child becomes a zombie. Finally, the parent appears to exit right after forking the child and creating an unused pipe (main
finishes) so I would have thought the child should be inherited byinit
so I don't know why it's becoming a zombie.fork
-then-exec
code, you should always call_exit
in the child after theexec
fails, notexit
. This is because callingexit
may execute cleanup code likeatexit
handlers that are only meant to be executed when the parent exits.dup2
ping file descriptors in order to be able to write to the launchedsh
, and get it's output. I.e. I want an application to be some kind of proxy tosh
(because the app communicates via interfaces/protocols which isn't known to a system).