當我使用file_sink
(在boost :: iostreams),然後fork()
子進程時,我觀察到一些奇怪的行爲。奇怪的行爲與分叉時提升file_sink
孩子繼續相同的代碼庫,即沒有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;
}
如果我運行此不帶參數(例如,./a.out
),以便它記錄到stderr
,然後我得到的預期輸出:
Log opened.
Parent exiting.
Hello World!
但是,如果我這樣做./a.out temp; sleep 2; cat temp
然後我得到:
Log opened.
Hello World!
因此,父母不知何故在分岔後不再寫入文件。這是謎題#1。
現在假設我只是將io::stream_buffer<io::file_sink> logbuf;
移到主體之外,以便它是一個全局變量。這樣做,並簡單地運行./a.out
給出如前面的情況相同的預期產量,但寫入文件(例如,溫度)現在給出了一個新的令人費解的行爲:
Log opened.
Parent exiting.
Log opened.
Hello World!
該行寫道:「日誌打開。」在fork()
之前,所以我不明白爲什麼它應該在輸出中出現兩次。 (我甚至在fork()
之前立即加上了一個明確的flush()
,以確保輸出行不是簡單緩衝的,然後在fork()
期間複製緩衝區,之後兩個副本最終都刷新到流中......)所以這就是拼圖# 2。
當然,如果我註釋掉整個fork()
過程(標記爲「第2步」整個一節),那麼它的行爲與預期兩個文件和stderr
輸出,也不管logbuf
是否是全局或局部於main()
。
另外,如果切換filelog
是的ofstream
代替stream_buffer<file_sink>
(參見main()
註釋行),那麼它也表現爲預期的兩種文件和stderr
輸出,也不管filelog
/logbuf
是否是全局的或局部的main()
。
所以它看起來真的,它是產生這些怪異的行爲file_sink
和fork()
之間的相互作用......如果任何人有什麼可能會造成這些想法,我會很感激的幫助!