Unregistered GC memory page with empty block last in a section and bad luck. #5509
Original bug ID: 5509
% head -n -0 t.ml default.ld.patch .gdbinit Makefile
==> default.ld.patch <==
==> .gdbinit <==
page <= 0xFFFF to avoid flood
==> Makefile <==
Program exited with code 02.
here one can see that the page=0x61f is not registered with caml_page_table_modify() in caml_main() despite that a caml value ([||]) is officially located in it (null size, at the begining, with its header in the previous page).
till then that confuses Classify_addr() which reports that the [||] is outside the heap, which in turn confuses Is_in_value_area() then compare_val():
naturally default.ld.patch is only there to reproduce by aligning the last [||] on a page end (multiple of 0x1000 = 2^12) ; and you may have to adapt it for your reproducing.
fyi, i originally hit this bug with Random.State.make [||] raising Division_by_zero when Lwt was initializing itself.
as a side note: i don't understand why more memory in .data is used for [||] instead of using the preallocated Atom(0).
The text was updated successfully, but these errors were encountered:
Comment author: @xavierleroy
This is the most elaborate repro case I've seen. I'm in awe.
I just committed (rev. 12166) a simple fix. Because some assemblers/linkers dislike symbols that point "one past" the end of a section, the ocamlopt code emitters already put an extra zero word at the end of the static data segments. (Well, the I386/MASM emitter did not, but it's now fixed.) Given this, I just included this zero word in the data segment as it is passed to caml_page_table_modify. I'm pretty sure this should fix the issue, but let me know if it isn't the case.
Using the atom table for empty static blocks is another possibility. It would require more special-casing in the code emitters, though, and I'd have to check that it wouldn't raise issues with dynamic loading of .cmxs files (normally not, but I'm not 100% sure at this point).