-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Ephemeron segfault with missing write barrier #9391
Copy link
Copy link
Closed
Description
Ephemerons don't use the normal write barrier, and because they're marked incrementally this can lead to the lost object problem, where an object becomes reachable only from an ephemeron that's already marked and never ends up getting marked.
It's difficult to trigger because it relies on the timing of incremental GC, but here's an example that hits the bug on trunk.
module E = Ephemeron.K1
let key = ref 1
let mk_ephe () =
let e = E.create () in
E.set_key e key;
e
let eph = mk_ephe ()
let other = ref "beep"
let () =
for stop = 100 to 2000 do
E.set_data eph (ref "hello");
Gc.major ();
Gc.minor (); Gc.major_slice 1 |> ignore; Gc.major_slice 1 |> ignore;
(* let _ = Array.init 1 (fun _ -> mk_ephe ()) in *)
let e = mk_ephe () in
(* let _ = Array.init 3 (fun _ -> mk_ephe ()) in *)
for i = 1 to 2000 do
Gc.major_slice 1 |> ignore;
if i = stop then begin
E.blit_data eph e;
E.set_data eph other;
end;
done;
let r = match E.get_data e with None -> assert false | Some r -> r in
Printf.printf "[%03d] %s\n%!" stop !r;
Gc.full_major ();
doneI'm not sure what the fix is. It may be as simple as adding darkening in blit_data (and maybe set_data?), but I don't understand what the marking invariants are for ephemerons.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels