2

我正在使用 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了。有什么方法可以将它与子进程分离?

4

1 回答 1

1

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

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

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

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

SIGPIPE程序的行为因子进程中的处理方式而异。如果它被忽略,write()则子进程中的 in 将失败,并且子进程将以非零退出代码退出。如果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] = '\0';
    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);
}
于 2019-11-08T10:24:01.680 回答