std::cin 进程分叉时未阻塞

std::cin is not blocking when process is forked

我有一个 C++ 控制台应用程序,它会自行分叉并关闭主进程。 如果按任意键,子进程中的 std::cin 不再阻塞。这导致无限循环。如果我之前没有分叉,那么应用程序会按预期运行。

我尝试了 cin::ignore、cin::fail、cin::clear 和 close 的不同组合来修复此问题,但没有成功。

我正在使用 Ubuntu 18.04.

为什么会发生这种情况,我该如何解决?

/* includes */
#include <iostream>
#include <unistd.h>
#include <limits>

void fork_to_background()
{
    pid_t f_return = fork();
    if (f_return == -1)
    {
        exit(1);
    }
    if (f_return != 0)
    {
        exit(0);
    }
}


int main(int argc, char** argv)
{
    fork_to_background();

    std::string commands;

    while(true)
    {
        std::cin >> commands;
        std::cout << "Loop" << std::endl;

        //std::cin.clear();
        //std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    }
}

std::cin >> 命令; 到达 EOF 时不会阻塞,您可以看到它检查是否 >> 成功,例如

if (! std::cin >> commands) {
   std::cout << "EOF" << std::endl;
   break;
}

您在评论中输入的两行在这里没有用,因为您读取的是一个字符串,它们在您读取一个数字而输入的不是有效数字的情况下很有用

注意父进程在 fork 之后立即退出,为子进程关闭 stdin 因为它们共享 stdin

如果我将您的程序修改为:

/* includes */
#include <stdlib.h>
#include <iostream>
#include <unistd.h>
#include <limits>
#include <sys/wait.h>

void fork_to_background()
{
    pid_t f_return = fork();
    if (f_return == -1)
    {
        exit(1);
    }
    if (f_return != 0)
    {
        waitpid(f_return, NULL, 0); // wait end of child
        exit(0);
    }
}

int main(int argc, char** argv)
{
    fork_to_background();

    std::string commands;

    while(std::cin >> commands)
    {
      std::cout << commands << std::endl;
      std::cout << "Loop" << std::endl;
    }

    std::cout << "done" << std::endl;
}

编译与执行:

/tmp % g++ -Wall f.cc
/tmp % echo "aze qsd" | ./a.out
aze
Loop
qsd
Loop
done
/tmp %