-
Notifications
You must be signed in to change notification settings - Fork 21
Description
Since using raylib-callbacks, I kept running into non-deterministic segfaults, despite the absence of any unsafe code. These typically occurred when heavy background tasks fired up.
I finally managed to isolate the situation. The problem seems to arise when Raylib.init_audio_device is invoked before Raylib.init_window, and a callback is set at some later point. Then in some future (seconds or hours later, probably dependent on GC load), some threads will crash.
The fix for me was to call init_audio only after init_window. I'm mystified why, perhaps somebody else has a clue. There is nothing in the Raylib docs that seems to suggest this constraint. Perhaps it's worth documenting with the binding?
See my repro case below, which crashes quickly on both Win and Mac. After switching lines [A] and [B] the crash disappears. Alternatively, likewise, if only one of the lines [1], [2], or [3] is commented out, which doesn't make a hell lot of sense to me. It's noteworthy that the callback isn't even invoked, since no audio is playing. Its sheer existence is cause enough — plus, even when detached again, crashes can still occur long after.
let pic = In_channel.(with_open_bin "pic.jpg" input_all) (* some random JPG *)
let rec run callback = (* pass callback around to keep closure alive *)
for _ = 0 to 3 do (* create some textures with finalisers *)
let image = Raylib.load_image_from_memory ".jpg" pic (String.length pic) in
let texture = Raylib.load_texture_from_image image in
Gc.finalise Raylib.unload_texture texture; (* [1] *)
Raylib.unload_image image (* [2] *)
done;
Unix.sleepf 0.02;
run callback
let rec pressure () =
Unix.sleepf 0.1;
Printf.printf "[allocating memory]\n%!";
ignore (Buffer.create 0x1_0000_0000);
pressure ()
let callback _ _ = ()
let _main =
Gc.(set {(get ()) with space_overhead = 20}); (* GC more often *)
Raylib.(set_trace_log_level TraceLogLevel.All);
Raylib.init_audio_device (); (* [A] *)
Raylib.init_window 100 100 "Crash test"; (* [B] *)
Raylib_callbacks.attach_audio_mixed_processor callback; (* [3] *)
ignore (Domain.spawn pressure);
run callback