On 22.09.2017 13:31, Dima Pasechnik wrote:
No, we have not done that before, and everything worked on Linux and OSX, and even on Cygwin (that is to say, we were lucky with threads implementations on these platforms, depending on some sort of undefined behaviour). Now I am trying ecl_import_current_thread/ecl_release_current_thread on FreeBSD, and it certainly appears to be the right direction, but I have a couple of questions, at least one of them related to signal handling.
- any advice on signal flags to be set to certain values?
Namely, ECL_OPT_SIGNAL_HANDLING_THREAD and ECL_OPT_THREAD_INTERRUPT_SIGNAL? They seem to affect the setup quite a bit; I had to do some trial and error, setting the former to 1 and the latter to 67 (probably OS-specific value) seemed to have done the trick...
- as ECL must be built with --enable-threads, does it mean
that it will also try to spawn threads on its own? (so far we always used to --disable-threads; for debugging purposes I'd rather not let ECL run its own threads)
[I'd say this is a documentation issue, too, as it's not clear what exactly --enable-threads is doing: enabling own ECL's threads, or enabling ECL embedding in a multithreaded program, or both?]
--enable-threads gives ECL ability to use threads (i.e programmer may create his own thread in Lisp program). ECL may be embedded in any scenario (having both threads enabled and disabled), but if threads for ECL are disabled, than it is calling program responsibility to assure that ECL is accessed synchronously (i.e no two functions in ECL at the same time are called).
ECL_OPT_SIGNAL_HANDLING_THREAD is a flag, which when set to 1 makes ECL create a separate thread meant for handling signals (so ECL in that case runs two threads). If ECL has threads disabled, then this flag does nothing.
- for some reason calling ecl_release_current_thread()
leads to a nasty crash, with lines like
frame #299974: 0x0000000883a52463
libecl.so.16.1`FElibc_error(msg="", narg=0) at error.d:490 frame #299975: 0x0000000883ab3e2c libecl.so.16.1`ecl_process_env at process.d:70 frame #299976: 0x0000000883aba9d4 libecl.so.16.1`ecl_alloc_compact_object(t=t_base_string, extra_space=12) at alloc_2.d:622 frame #299977: 0x0000000883a8c782 libecl.so.16.1`ecl_alloc_simple_vector(l=11, aet=ecl_aet_bc) at array.d:585 frame #299978: 0x0000000883a5331d libecl.so.16.1`make_base_string_copy(s="No error: 0") at string.d:136 frame #299979: 0x0000000883a52320 libecl.so.16.1`_ecl_strerror(code=0) at error.d:475 frame #299980: 0x0000000883a52463
repeating endlessly in the backtrace. Must it be called at all? (The test program in examples you pointed at does work for me, with few makefile changes...)
- How does one call cl_boot() in such a multithreaded setting? I
tried merely putting the call to
ecl_import_current_thread()
before the call to
cl_boot()
but I get an error from GC:
"Threads explicit registering is not previously enabled" and the program aborts. Without doing ecl_import_current_thread(), cl_boot() succeeds in "main" thread, but coredumps if invoked from another thread---this is the behaviour you mistook for another instance of GC kicking in)
While we probably can live with cl_boot() always being called in the main thread, this would be an extra burden to implement...
ecl_import_current_thread and ecl_release_current_thread needs to be called in threads, which call ECL and are different than thread where cl_boot is called. For the thread where cl_boot was called you don't call import/release, they are implicit for cl_boot / cl_shutdown. You may run cl_boot in thread not being main one, that's not the issue.
- GC_THREADS is #define'd both in ECL and in GC headers.
This seems wrong to me.
No idea why it is that way. I'll keep in mind investigating that.
Regards, Daniel