有没有办法在一段时间后从外流中分离进程?

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

我正在使用 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] = '[=10=]';
    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 SIGPIPE\n");
    }
    if (WIFEXITED(stat)) {
        printf("\nChild exited with exit code %d\n", WEXITSTATUS(stat));
    }

    exit(0);
}