Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Two threads communicating over a Unix pipe may lockup at exit #4009

Closed
vicuna opened this issue Apr 24, 2006 · 1 comment
Closed

Two threads communicating over a Unix pipe may lockup at exit #4009

vicuna opened this issue Apr 24, 2006 · 1 comment

Comments

@vicuna
Copy link

vicuna commented Apr 24, 2006

Original bug ID: 4009
Reporter: berke
Status: closed (set by @xavierleroy on 2006-06-13T09:54:05Z)
Resolution: won't fix
Priority: normal
Severity: minor
Version: 3.09.2
Category: ~DO NOT USE (was: OCaml general)
Monitored by: @mmottl

Bug description

Hello,

I have a program where I create a Unix pipe for inter-thread communication. I know, this sounds weird, but this was the only way to feed back libcamlzip's output to streams without using Stream.from_function which is unbuffered and thus dead slow. I then create input and output channels from the descriptors
of the pipe. Thread 2 then writes data while thread 1 reads it. If the program
terminates before thread 1 has finished writing, under certain conditions, the program will lock at exit. Xavier found that this is due to the exit procedure attempting to acquire locks on thread 2's output channel in order to flush it.
Anyway, here is an example reproducing the problem. Note that fiddling with the timing or the number of lines read or written changes the outcome.

The workaround is to close the input channel before exiting the first thread.

% cat lockup.ml
(* Minimal lock-up example *)

let _ =
let (pr,pw) = Unix.pipe () in
let (ic,oc) = (Unix.in_channel_of_descr pr, Unix.out_channel_of_descr pw) in
let _ = Thread.create
begin fun () ->
let w = String.make 4096 ' ' in
w.[4095] <- '\n';
for i = 1 to 100 do
Printf.eprintf "Wrote line %d\n%!" i;
output_string oc w
done;
close_out oc
end
()
in
for j = 1 to 7 do
ignore (input_line ic);
Printf.printf "Read line %d\n%!" j;
ignore (Unix.select [] [] [] 0.05);
done;
;;
% ocamlopt.opt -thread unix.cmxa threads.cmxa lockup.ml -o lockup
% ./lockup
Wrote line 1
Read line 1
Wrote line 2
Wrote line 3
Wrote line 4
Wrote line 5
Wrote line 6
Wrote line 7
Wrote line 8
Wrote line 9
Wrote line 10
Wrote line 11
Wrote line 12
Wrote line 13
Wrote line 14
Wrote line 15
Wrote line 16
Wrote line 17
Wrote line 18
Read line 2
Wrote line 19
Read line 3
Wrote line 20
Read line 4
Wrote line 21
Read line 5
Wrote line 22
Read line 6
Wrote line 23
Read line 7
Wrote line 24
...

@vicuna
Copy link
Author

vicuna commented Jun 13, 2006

Comment author: @xavierleroy

This is unfortunate, but I don't see any way to avoid this behavior, given that 1- we must lock all blocking operations over channels, and 2- flushing all output channels at exit is highly desirable. So, I'm closing this PR for the time being.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant