I have the following simple OCaml Async job which is supposed to write to a file and terminate the process.
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
However, it seems that fd
gets closed before the write is performed (part of displayed sexp is "writer fd unexpectedly closed"). Is there a way to wait for write to complete before closing the file descriptor? Actually, I don't understand why Writer.write
doesn't return a Deferred.t
just as Reader.read
does. Wouldn't it solve the issue?
My problem is actually a little more general. Basically, I have a periodic job that writes something to a file using Clock.every'
. The program can exit at any time and close the file descriptors. How to make sure that all the writes are processed before the fd
get closed?
If my stopping job is:
Unix.close fd
>>= fun () ->
exit 0
A scheduled write can very well happen between Unix.close fd
and exit 0
.
In your particular case, you shouldn't close the file descriptor directly with the Unix.close
function. The idea is that you actually moved the ownership of fd
to the writer, so it is now the writer's responsibility to close the file descriptor. So, you need to use Writer.close
that returns a unit deferred. This function, will wait until all pending writes are finished, and then close the file descriptor, e.g.,
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
Answering your more general question "Is there a way to wait for write to complete before closing the file descriptor?". Yes, Writer.close
will wait. In the sence that it will return a deferred that will become determined after everything is written and fd is closed. You can also use a force_close
parameter, that will force the closing operation leading to abrupt writes, if it considered a better option to the hanging program. E.g., you can give a program a reasonable amount of time to flush data, and then terminate with an error.