C++ 分叉时boost file_sink的奇怪行为

C++ 分叉时boost file_sink的奇怪行为,c++,boost,file-io,process,fork,C++,Boost,File Io,Process,Fork,当我使用文件\u sink(在boost::iostreams中)然后使用fork()子进程时,我观察到一些奇怪的行为 子进程继续执行相同的代码基,即noexec()调用,因为这是作为守护进程的一部分完成的。当然,我的完整代码完全监视了这个过程,但是我省略了那些对于重新生成行为来说不必要的步骤 以下代码是演示该行为的简化示例: using namespace std; namespace io = boost::iostreams; void daemonize(std::ostream&am

当我使用
文件\u sink
(在boost::iostreams中)然后使用
fork()
子进程时,我观察到一些奇怪的行为

子进程继续执行相同的代码基,即no
exec()
调用,因为这是作为守护进程的一部分完成的。当然,我的完整代码完全监视了这个过程,但是我省略了那些对于重新生成行为来说不必要的步骤

以下代码是演示该行为的简化示例:

using namespace std;
namespace io = boost::iostreams;

void daemonize(std::ostream& log);


int main (int argc, char** argv)
{
  io::stream_buffer<io::file_sink> logbuf;
  std::ostream filelog(&logbuf);
  //std::ofstream filelog;

  // Step 1: open log
  if (argc > 1)
  {
    //filelog.open(argv[1]);
    logbuf.open(io::file_sink(argv[1]));
    daemonize(filelog);
  }
  else
    daemonize(std::cerr);

  return EXIT_SUCCESS;
}


void daemonize(std::ostream& log)
{
  log << "Log opened." << endl;

  // Step 2: fork - parent stops, child continues
  log.flush();
  pid_t pid = fork(); // error checking omitted

  if (pid > 0)
  {
    log << "Parent exiting." << endl;
    exit(EXIT_SUCCESS);
  }
  assert(0 == pid); // child continues

  // Step 3: write to log
  sleep(1); // give parent process time to exit
  log << "Hello World!" << endl;
}
Log opened.
Parent exiting.
Log opened.
Hello World!
但是,如果我执行类似于
/a.out temp;睡眠2;cat温度
然后我得到:

Log opened.
Hello World!
因此,父对象不知何故不再在fork之后写入文件。这就是谜题1

现在假设我只移动
io::stream\u buffer logbuf在main之外,因此它是一个全局变量。这样做,只需运行
/a.out
即可获得与前一种情况相同的预期输出,但写入文件(例如temp)现在会产生新的令人费解的行为:

using namespace std;
namespace io = boost::iostreams;

void daemonize(std::ostream& log);


int main (int argc, char** argv)
{
  io::stream_buffer<io::file_sink> logbuf;
  std::ostream filelog(&logbuf);
  //std::ofstream filelog;

  // Step 1: open log
  if (argc > 1)
  {
    //filelog.open(argv[1]);
    logbuf.open(io::file_sink(argv[1]));
    daemonize(filelog);
  }
  else
    daemonize(std::cerr);

  return EXIT_SUCCESS;
}


void daemonize(std::ostream& log)
{
  log << "Log opened." << endl;

  // Step 2: fork - parent stops, child continues
  log.flush();
  pid_t pid = fork(); // error checking omitted

  if (pid > 0)
  {
    log << "Parent exiting." << endl;
    exit(EXIT_SUCCESS);
  }
  assert(0 == pid); // child continues

  // Step 3: write to log
  sleep(1); // give parent process time to exit
  log << "Hello World!" << endl;
}
Log opened.
Parent exiting.
Log opened.
Hello World!
写入“Log opened.”的行位于
fork()前面,所以我不明白为什么输出中会出现两次。(我甚至在
fork()
之前放了一个显式的
flush()
,以确保输出行不是简单的缓冲,然后在
fork()
期间复制了缓冲区,后来两个副本最终都刷新到流中……)这就是谜题2

当然,如果我注释掉整个
fork()
过程(标记为“步骤2”的整个部分),那么无论
logbuf
是全局的还是本地的
main()
,它的行为都与文件和
stderr
输出的预期一样

此外,如果我将
filelog
切换为流的
,而不是
stream\u buffer
(请参见
main()
中注释掉的行),那么它的行为也与文件和
stderr
输出的预期一样,并且无论
filelog
/
logbuf
是全局的还是本地的
main()


因此,它似乎真的是
file\u sink
fork()
之间的交互作用,产生了这些奇怪的行为。。。如果有人知道是什么导致了这些,我将非常感谢你的帮助

我想我知道了。。。为子孙后代/任何偶然发现这个问题并寻求答案的人创造这个答案

我在boost 1.40中观察到了这种行为,但当我使用boost 1.46进行尝试时,在所有情况下,一切都以预期的方式进行,即:

Log opened.
Parent exiting.
Hello World!
所以我现在的假设是,这实际上是boost中的一个bug,在版本1.41-1.46之间修复了。我在发行说明中没有看到任何明显的东西,他们发现并修复了这个bug,但发行说明中可能讨论了修复这个bug的一些潜在原因,我无法在这个潜在原因和这个场景之间做出关联

无论如何,解决方案似乎是安装boost版本>=1.46