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()
子进程时,我观察到一些奇怪的行为
子进程继续执行相同的代码基,即noexec()
调用,因为这是作为守护进程的一部分完成的。当然,我的完整代码完全监视了这个过程,但是我省略了那些对于重新生成行为来说不必要的步骤
以下代码是演示该行为的简化示例:
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