Skip to content

Crashes with Raylib-callbacks #73

@rossberg

Description

@rossberg

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions