有没有办法在一段时间后将流程从流出中分离出来

Is there way to detach process from out-stream after some time?

本文关键字:分离出 一段时间 有没有      更新时间:2023-10-16

我正在使用boost::process::child来生成新进程。我正在启动的进程的启动时间不是即时的,所以我必须等待一段时间,直到它完全初始化

auto is_ptr = std::make_shared<bp::ipstream>();
auto child_pr = std::make_shared<bp::child>(executable, args, bp::std_out > *is_ptr);
m_childs[port] = {child_pr, is_ptr};
std::string line;
while (child_pr->running() && std::getline(*is_ptr, line)) {
std::cerr <<"SI: t" << line << std::endl;
if( 0 == line.compare(0, string_to_find.size(), string_to_find)){
break;
}
}
...

在这个周期之后,我不再需要ipstream了。有没有办法将它从子进程中分离出来?

由于您要求提供答案,我将在此处提供一些附加信息,尽管我不确定它是否能完全回答您的问题。

假设目标平台是Linux,一旦ipstream在父进程中被销毁,这实际上意味着父进程和子进程之间关联管道的文件描述符在父进程中将被关闭。一旦子进程在父进程关闭其管道的读取端之后写入管道,就会为子进程生成SIGPIPE,这将导致它在不采取额外措施的情况下终止。

为了防止这种情况,一个选项是忽略子级中的SIGPIPE。这将在写入该管道时导致子进程出错。这取决于子进程的实施,这将产生什么原因。在您的情况下,解决方案可能是忽略SIGPIPE,并在子进程无法再成功写入数据时采取措施,以防止浪费大量CPU周期。

要在较低级别上对此进行实验,可以使用以下程序。它将派生一个子进程,只要成功,该子进程就会继续写入某些输出。一旦父进程从中读取了一些数据,它就会关闭相应的管道

程序的行为因子进程中SIGPIPE的处理方式而异。如果忽略它,则子进程中的write()将失败,并且子进程将使用非零退出代码退出。如果不忽略SIGPIPE,则操作系统将终止子进程。父进程将告诉您子进程中发生了什么。

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(int argc, char** argv)
{
int pipe_fds[2];
if (pipe(pipe_fds) < 0) {
perror("pipe");
exit(1);
}
pid_t pid;
if ((pid = fork()) < 0) {
perror("fork");
exit(1);
}
if (pid == 0)
{
close(pipe_fds[0]); /* close read-end in the child */
/* Uncomment the following line, and the child will terminate as soon
as the parent closes the read end of the pipe...This is here merely
for illustrative purposes, production code should use either
sigaction() or pthreads related signal functionality in case of a
multi-threaded program. */
/* signal(SIGPIPE, SIG_IGN); */
/* Child process, start writing to the write-end of the pipe. */
const char message[] = "Hello world!n";
while (write(pipe_fds[1], message, strlen(message)) >= 0);
exit(1);
}
close(pipe_fds[1]);
char buf[256];
ssize_t count;
while ((count = read(pipe_fds[0], buf, sizeof(buf) - 1)) == 0);
if (count < 0) {
perror("read");
exit(1);
}
buf[count] = '';
printf("%s", buf);
/* Close read-end in the parent, this will trigger SIGPIPE in the child
once the child writes to the pipe. */
close(pipe_fds[0]);
int stat;
if (waitpid(pid, &stat, 0) < 0) {
perror("waitpid");
exit(1);
}
if (WIFSIGNALED(stat) && WTERMSIG(stat) == SIGPIPE) {
printf("nChild terminated by SIGPIPEn");
}
if (WIFEXITED(stat)) {
printf("nChild exited with exit code %dn", WEXITSTATUS(stat));
}
exit(0);
}