> the following issue has occurred when embedding CHICKEN 5.4.0 in a
> multithreaded C program. I have reproduced the issue on macOS and
> NetBSD 10. Either I am doing something wrong or this is a bug.
>
> The program I am embedding just returns the squared input.
>
>     ;; x.scm
>     (import (chicken platform) (chicken foreign))
>
>     (define-external (bar (int i)) int
>         (* i i))
>
>     (return-to-host)
>
> The C program starts one extra thread and then both threads
> call the exported function bar. To ensure no concurrency issues
> occur, I have protected the calls to bar with a pthread mutex.
>
> [...]
>
> From CHICKEN's documentation, I had the impression that this
> interface usage should be supported. Am I doing something silly?

You are doing nothing wrong, it is just a limitation of the runtime system.
CHICKEN expects callbacks to be invoked in the same thread as the
one that invoked CHICKEN_run()/CHICKEN_initialize(). During
initialization, stack-limits are inferred to ensure the generational
garbage collector sees when the nursery is exhausted. Different
thread have of course wildly different stack addresses, so this
will confuse the garbage collector. You could say that this is a severe
shortcoming (not necessarily a bug), and we could try to set the limits on
every external call-in into the runtime system.

>
> Last comment: I have started this with gdb and one thread does
> not leave C_save_and_reclaim, IIRC. I keeps calling some
> mark_* and C_reclaim functions.  My libchicken does not have
> symbols, so I couldn't look in more details what is happening,
> but it looks like the thread never leaves the function. That
> only happens if I call the interface with two or more threads.

Apparently the GC gets stuck, due to the wrong stack addresses
(so it always assumes the stack is exhaused and repeats
collecting).

There is an egg ("concurrent-native-callbacks") that addresses
this very issue (calling from multiple threads into compiled
CHICKEN code). It is not as elegant or clean as calling from
multiple threads directly, but it is at least one possible approach.

I hope this helps.


cheers,
felix


Reply via email to