Bugs: Browse | Download .csv
According to the docs > some IO.outputs are built on top of other IO.outputs for the same > purpose (e.g. on-the-fly compression of a file or network > information). In this case, closing the "outer" IO.input/IO.output > (e.g. the decompressor/compressor) will not close the "inner" > IO.input/IO.output (e.g. access to the file or to the network). You > will need to close the "inner" IO.input/IO.output, which will > automatically flush the outer IO.input/IO.output and close it. It seems to me that this is happening with the following code: let r,w = Unix.open_process "cat";; Printf.fprintf w "hello world\n";; close_out w;; try while true do print_char (input_char r) done with _ -> ();; Compiled in batteries the result hangs. Compiled with straight ocamlc it prints "hello world". Most likely culprit is the close_out not operating correctly. However I don't see in the docs a way close the underlying IO.output. Either the docs are buggy or something else is wrong. File attached, compile with ocamlc unix.cma t.ml -o t or ocamlfind batteries/ocamlc t.ml -o t and run with ./t
Date: 2009-06-20 15:32 Sender: David Teller Yes, we should probably get [cleanup] to be true by default.
Date: 2009-06-20 06:24 Sender: Trevor Jim Well, I was misled because I was used to the ocaml version, and I looked back at the ocaml documentation, and at various examples people have posted over some years. I think, therefore, that changing the behavior wrt the ocaml version has downsides :-). Also, Unix and networking books (e.g., Stevens) will tell you to close the file descriptor in this case. Of course, this is not a file descriptor but still, I'm likely to be looking at a networking book when doing this sort of thing. I'm not even sure what "[close_out] closes the output but not the underlying process" means. How is the output closed if the underlying **file descriptor** is not closed? And closing the file descriptor does not kill the process, if that's what you mean by "closing" a process. So I'm voting to restore the original behavior :-)
Date: 2009-06-19 22:02 Sender: David Teller After a complex sequence of debugging, I took the time to read my own documentation and realized that this was actually the documented behavior: by default, [close_out] closes the output but not the underlying process. If you want the process to close when [close_out] is invoked, you should create it with [~cleanup:true]. Now, the question is: should we change the behavior?
Date: 2009-06-19 17:26 Sender: David Teller I have just added a test for this bug to the testsuite. Strangely, the test seems to work. It uses IO.read_line which might be the reason for difference. This is puzzling.
Date: 2009-06-19 16:23 Sender: Trevor Jim Here is a workaround: let r,w = Unix.open_process "cat";; Printf.fprintf w "hello world\n";; flush w;; close_out w;; try let fd = Unix.descr_of_out_channel w in Unix.close fd with _ -> ();; try while true do print_char (input_char r) done with _ -> ();; I have added a flush and a Unix.close. The Unix.close is necessary, the batteries version hangs without it.
Date: 2009-06-19 16:15 Sender: Trevor Jim I don't think it is a flushing problem, or, if so, that's an additional issue. (I have tried explicitly flushing and that doesn't help, and looking at the source it seems to flush.) Furthermore I have run strace on both versions. In the batteries version I can see that "hello world\n" is written and also read. Then there is another read that hangs. The cat process is waiting for the EOF before it prints anything. I also see a close in the non-batteries version and no close in the batteries version.
Date: 2009-06-19 07:55 Sender: David Teller Indeed, there seems to be a problem with flushing.