I’m using ctypes to write C bindings to a library that allows the user to register a callback that is called when a specific event occurs. The C function that allows you to register this callback takes a function pointer and calls it when the event fires.
The problem is the library spawns a new pthread to check for new events and call the function pointer. This means that if I use
Ctypes.Foreign.funptr to give it an OCaml function, the runtime lock is not acquired when the function is called, leading to a segfault.
I ran the program through lldb and received this backtrace, which leads me to believe that it is, in fact, a runtime issue:
(lldb) r Process 3572 launched: '/Users/zbaylin/Development/ocaml-rtmidi/_build/default/example/ocaml_rtmidi_example.exe' (x86_64) 4302327232 ocaml_rtmidi_example.exe was compiled with optimization - stepping may behave oddly; variables may not be available. Process 3572 stopped * thread #2, stop reason = EXC_BAD_ACCESS (code=1, address=0x18) frame #0: 0x0000000100073c1b ocaml_rtmidi_example.exe`caml_thread_leave_blocking_section [inlined] caml_thread_restore_runtime_state at st_stubs.c:202:43 [opt] Target 0: (ocaml_rtmidi_example.exe) stopped. (lldb) bt * thread #2, stop reason = EXC_BAD_ACCESS (code=1, address=0x18) * frame #0: 0x0000000100073c1b ocaml_rtmidi_example.exe`caml_thread_leave_blocking_section [inlined] caml_thread_restore_runtime_state at st_stubs.c:202:43 [opt] frame #1: 0x0000000100073c1b ocaml_rtmidi_example.exe`caml_thread_leave_blocking_section at st_stubs.c:248:3 [opt] frame #2: 0x00000001000844a3 ocaml_rtmidi_example.exe`caml_leave_blocking_section at signals.c:175:3 [opt] frame #3: 0x000000010009e6ef ocaml_rtmidi_example.exe`caml_write_fd(fd=2, flags=<unavailable>, buf=0x0000000108448048, n=11) at unix.c:94:3 [opt] frame #4: 0x0000000100092f3f ocaml_rtmidi_example.exe`caml_flush_partial(channel=0x0000000108448000) at io.c:194:15 [opt] frame #5: 0x0000000100093e28 ocaml_rtmidi_example.exe`caml_ml_flush [inlined] caml_flush at io.c:209:12 [opt] frame #6: 0x0000000100093e1e ocaml_rtmidi_example.exe`caml_ml_flush(vchannel=<unavailable>) at io.c:667:3 [opt] frame #7: 0x000000010002b207 ocaml_rtmidi_example.exe`camlStdlib__prerr_endline_386 + 87
I saw that
funptr has an optional
runtime_lock argument, but this allows the user to specify that they want to specifically release the runtime lock, not acquire it.
tl;dr: are there any examples of people using ctypes in an asynchronous manner such as this? I think I could do this writing C bindings on my own, but I’d prefer not to mix custom stubs with ctypes if I don’t have to.