caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* [Caml-list] C, threads, callbacks, and corrupted local_roots
@ 2019-06-20 18:03 rixed
  2019-06-21  7:30 ` Sébastien Hinderer
  0 siblings, 1 reply; 6+ messages in thread
From: rixed @ 2019-06-20 18:03 UTC (permalink / raw)
  To: caml-list

[-- Attachment #1: Type: text/plain, Size: 2051 bytes --]

Hello !

I have a programs which entry point is in C++ and that spawn a few threads, some of which are calling back some OCaml code. 
My understanding is that for this to work, one must only follow those rules (in addition to the usual "how to leave in peace with the GC" rules:

1. call caml_startup(argv) before any OCaml code or any other function from the OCaml runtime is run;

2. for each thread that will eventually run some OCaml code (anything that could call the GC (and also, possibly, do anything with signals)), call caml_c_thread_register before;

3. before a thread terminates and another thread runs the OCaml GC, call (from that terminating thread) caml_c_thread_unregister (it is not clear exactly why to be honest, as a finished thread should have no root left)

What is a bit unclear is how thread registering and caml_startup are supposed to deal with the giant lock. From testing and
reading the code, it seems that caml_c_thread_(un)register expects the giant lock to be released, which caml_startup does not do, so calling caml_release_runtime_system right after caml_startup seems in order (and therefore reacquiring it before calling back to OCaml).

Neither is it clear to me how to declare local roots in the function registering the thread (more specifically: should caml_c_thread_register be called first, then a new block created and CAMLparam and friends be called now that the current root list is initialized?); But in the exemple below it does not matter as there are no values requiring such protection.

Yet, whatever I try, I get a crash in the Gc when it's scaninng the roots in caml_do_local_roots, with a corrupted local_root pointer that is suspiciously small (few hundred bytes, frequently but not always just 0xfff). I am not certain about those values though, as I'm not using a debug runtime (opam had such debug variants for a couple of old ocaml versions but not any longer it seems)

Thankfully, the attached minimal example dies in the exact same circumstances.

Do anyone know what I am doing wrong?

[-- Attachment #2: Makefile --]
[-- Type: application/octet-stream, Size: 424 bytes --]

OCAMLLIB = $(shell ocamlfind ocamlc -where)
CFLAGS += -g -O0 -Wall -W -fPIC -fstandalone-debug
CPPFLAGS += -I $(OCAMLLIB)
LDFLAGS += -L$(OCAMLLIB) -lunix -lcamlstr -lthreads -lasmrun_shared

all: b

b: a.o b.o

a.cmx: a.ml
	ocamlfind ocamlopt -thread -package threads -c $< -o $@

a.o: a.cmx
	ocamlfind ocamlopt -thread -package threads -linkpkg $< -output-obj -o a.tmp.o
	mv a.tmp.o $@

clean:
	$(RM) *.o *.cmx *.cmi b *.s

[-- Attachment #3: a.ml --]
[-- Type: application/octet-stream, Size: 217 bytes --]

let call_me_from_c () =
  Printf.printf "Will I survive?\n%!" ;
  Gc.compact () ;
  Printf.printf "I survived!\n%!"

let init =
  ignore (Thread.self ()) ;
  ignore (Callback.register "call_me_from_c" call_me_from_c)

[-- Attachment #4: b.c --]
[-- Type: application/octet-stream, Size: 704 bytes --]

#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <caml/mlvalues.h>
#include <caml/startup.h>
#include <caml/callback.h>
#include <caml/threads.h>

static void *another_thread(void *wtv)
{
  (void)wtv;
  caml_c_thread_register();
  printf("in another_thread\n");
  caml_acquire_runtime_system();
  value *cb = caml_named_value("call_me_from_c");
  caml_callback(*cb, Val_unit);
  caml_release_runtime_system();
  caml_c_thread_unregister();
  return NULL;
}

int main(int argc, char *argv[])
{
  (void)argc;
  caml_startup(argv);
  caml_release_runtime_system();

  pthread_t th;
  (void)pthread_create(&th, NULL, another_thread, NULL);

  (void)pthread_join(th, NULL);

  return 0;
}

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2019-06-21 14:01 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-06-20 18:03 [Caml-list] C, threads, callbacks, and corrupted local_roots rixed
2019-06-21  7:30 ` Sébastien Hinderer
2019-06-21 10:51   ` rixed
2019-06-21 11:38     ` Sébastien Hinderer
2019-06-21 12:21       ` rixed
2019-06-21 14:00         ` Sébastien Hinderer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).