2017-07-17 83 views
1

我有以下簡單的OCaml異步作業,它應該寫入文件並終止進程。等待Writer.write在Caml中完成Async

Unix.openfile "foobar" ~mode:[`Creat;`Rdwr] 
>>= fun fd -> 
let wr = Writer.create fd in 
Writer.write wr "this is a test"; 
Unix.close fd 
>>= fun() -> 
exit 0 

然而,似乎在執行寫入之前fd被關閉(顯示SEXP的一部分,是「作家FD意外關閉」)。有沒有辦法在關閉文件描述符之前等待寫入完成?其實,我不明白爲什麼Writer.write沒有返回Deferred.t,就像Reader.read一樣。它不會解決問題嗎?

我的問題其實是更一般一點。基本上,我有一個使用Clock.every'將文件寫入文件的定期作業。該程序可以隨時退出並關閉文件描述符。如何確保在fd關閉之前處理所有寫入操作?

如果我停止工作是:

Unix.close fd 
>>= fun() -> 
exit 0 

一個定時寫能很好Unix.close fdexit 0之間發生。

回答

1

在您的特定情況下,您不應該直接使用Unix.close函數關閉文件描述符。這個想法是,您實際上已將fd的所有權移交給作者,因此現在作者有責任關閉文件描述符。所以,你需要使用返回延遲單位的Writer.close。此功能,將等到所有掛起寫操作完成後,再關閉文件描述符,例如,

Unix.openfile "foobar" ~mode:[`Creat;`Rdwr] 
>>= fun fd -> 
let wr = Writer.create fd in 
Writer.write wr "this is a test"; 
Writer.close fd 
>>= fun() -> 
exit 0 

回答您的更普遍的問題:「有沒有辦法等待寫入關閉文件描述符前完成? 」。是的,Writer.close將等待。在它將返回一個延遲,它會在寫完所有內容並且fd被關閉後確定。您也可以使用force_close參數,如果它認爲懸掛程序的更好選項,則該參數將強制關閉操作導致突然寫入。例如,你可以給程序一個合理的時間來刷新數據,然後終止一個錯誤。

+0

謝謝,這回答我的問題。然而,這是什麼意思,我把所有權移交給作家?假設我想在第一次寫入其他東西之後再次使用fd,比如在文件的另一部分寫一個'lseek'來寫。在那種情況下,我不得不等待第一次寫入,但我不想關閉文件描述符。有沒有辦法做到這一點? – Nemo

+1

那麼你的程序最終會被破壞,這與C流庫和任何其他緩衝IO一樣,一旦你傳遞了一個描述符,不要再直接使用描述符,除非你真的明白髮生了什麼在引擎蓋下面。這不僅是關閉調用的問題,而且是普通寫入的問題,這不會隨着寫入器的緩衝寫入而出現。所以我的建議是,要麼根本不使用'Writer'接口,要麼在任何地方都使用Writer接口。不要試圖粘在中間的某個地方。 – ivg

+0

謝謝,我會試圖弄清楚這一點。如有需要,我會問一個新問題。 – Nemo