问题
I'm writing an application which will start some processes (fork and exec) depending on users input and should inform user about every error in those processes (Print some internal ID + message written to stderr by the process). I'd also like to detect exiting processes. I'm facing the problem, that I cannot receive data after executing execl() command. Test data is received in epoll_wait loop, but process called by exec seems to not write anything to stderr nor even end (I don't know if I'm correct, but I expect pipe to be readable after it's writing end has been closed, when process exited). Some code reproducing my problem:
#include <unistd.h>
#include <sys/epoll.h>
#include <stdio.h>
#include <thread>
#include <stdlib.h>
#include <sys/wait.h>
thread_local int epoll;
int do_fork()
{
int pip[2];
pipe(pip);
int pid = fork();
if (pid == 0)
{
dup2(pip[1], STDERR_FILENO);
close(pip[0]);
close(pip[1]);
write(STDERR_FILENO, "test data", 10);
sleep(3);
//exit(1);
execl("tr", "tr", NULL); //this process will end immediately and write error on stderr
}
else
{
printf("PID %d\n", pid);
close(pip[1]);
epoll_event ev;
ev.data.fd = pip[0];
ev.events = EPOLLIN | EPOLLRDHUP | EPOLLHUP;
printf("pipe %d\n", pip[0]);
epoll_ctl(epoll, EPOLL_CTL_ADD, pip[0], &ev);
}
}
int thread()
{
epoll_event events[10];
epoll = epoll_create1(0);
epoll_event ev;
ev.data.fd = STDIN_FILENO;
ev.events = EPOLLIN;
epoll_ctl(epoll, EPOLL_CTL_ADD, STDIN_FILENO, &ev);
char buf[1000];
while(true)
{
int r = epoll_wait(epoll, events, 10, -1);
printf("r = %d\n", r);
for (int i = 0; i < r; ++i)
{
if(events[i].data.fd == STDIN_FILENO)
{
int t = read(events[i].data.fd, buf, 1000);
do_fork();
}
else
{
printf("event? %d\n", events[i].events);
printf("pipe %d\n", events[i].data.fd);
int t = read(events[i].data.fd, buf, 1000);
printf("t == %d\n", t);
if(t == -1)
printf("errno: %d\n", errno);
if(events[i].events & EPOLLHUP || t == 0)
{
epoll_ctl(epoll, EPOLL_CTL_DEL, events[i].data.fd, NULL);
if(close(events[i].data.fd) == -1)
printf("cannot close fd\n");
}
}
}
}
return 0;
}
int main()
{
std::thread t{thread};
t.detach();
while(true);
}
来源:https://stackoverflow.com/questions/37375047/communication-with-child-process-using-pipes-and-epoll