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
threads and marshalling with I/O #2359
Comments
Comment author: administrator
Please keep in mind that the two thread libraries for Caml are set up in such a Marshalling is a two-step process: first, the stream of bytes is built in
I'll look at that. One quick question: is this with bytecode threads or native Best regards,
|
Comment author: administrator On Mon, 17 Jan 2000, you wrote:
I already took the master lock into account. The buffers that are used for void output_val(struct channel *chan, value v, value flags) Although "extern_block" is copied into the channel's private buffer, it is still
A possible solution would be to free extern_block immediately after it has The same problem applies to "input_val", because "intern_input" can be used by There is another problem with input_val: value input_val(struct channel *chan) really_getblock simply does getblock multiple times with the same buffer. int getblock(struct channel *channel, char p, long int len) "do_read" then passes "p" over to "read", with released master lock. This may also be the reason for the Pervasives.input bug I reported, too,
Native threads, of course. GerdGerd Stolpmann Telefon: +49 6151 997705 (privat)
|
Comment author: administrator
You are correct, "stat_free(extern_block)" in output_val isn't protected by
Unfortunately, the channel buffer doesn't always have enough free room to copy My fix is to save the value of extern_block (the address of the extern buffer)
Right. (My fix above is symmetrical). This will be in 3.00.
Correct. There was a similar bug in Unix.read and Unix.write that was fixed a I have fixed this by suppressing the optimization in getblock (that we read Thanks for the bug reports and diagnostics,
|
Comment author: administrator Fixed in 3.00 |
Original bug ID: 25
Reporter: administrator
Status: closed
Resolution: fixed
Priority: normal
Severity: minor
Category: ~DO NOT USE (was: OCaml general)
Bug description
Full_Name: Gerd Stolpmann
Version: 2.04 -with-pthread
OS: Linux-2.2.13 with glibc-6.1
Submission from: master.proxy.ision.net (195.180.208.40)
Marshalling, including the input/output_value functions in Pervasives, is not
reentrant at all. This very clear from the C source code in byterun/extern.c
and
intern.c:
extern.c: There is a static variable extern_block which is actually the buffer
that is written in do_write; writing happens in a "blocking section" and so
concurrent Marshal.to_channel calls can lead to situations where more than one
thread is executing the code within this section with the same extern_block
buffer.
intern.c: The same problems with the buffer intern_input which is also filled
in a blocking section.
This piece of code often segfaults with Marshal.to_channel:
let l = ref [] in
let s = String.make 10000 'x' in
for i = 1 to 50 do
let id =
Thread.create
(fun () ->
for j = 1 to 100 do
let ch = open_out "/dev/null" in
Marshal.to_channel ch s [];
close_out ch;
done;
)
()
in
l := id :: !l
done;
List.iter
(fun id ->
Thread.join id)
!l
;;
The same with Marshal.from_channel:
let s = String.make 10000 'x' in
let out = open_out "r.data" in
Marshal.to_channel out s [];
close_out out;
let l = ref [] in
for i = 1 to 50 do
let id =
Thread.create
(fun () ->
for j = 1 to 100 do
let ch = open_in "r.data" in
ignore(Marshal.from_channel ch);
close_in ch;
done;
)
()
in
l := id :: !l
done;
List.iter
(fun id ->
Thread.join id)
!l
;;
The text was updated successfully, but these errors were encountered: