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.
0) 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...
1) 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.
2) 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...)
3) 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.
4) 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