We have to make sure that the stack pointers always point to a
valid object. This means that we have to increase env->stack_top
before we change things in the stack.
If a thread is interrupted directly after a call to
ecl_function_dispatch, env->function may be overwritten before
it is used. Thus we need to save and restore when we
execute queued signals.
The logic im mp_barrier_wait is wrong. decrement_counter returns
the value of the counter __before__ it is decremented. Before
the fix, the counter decremented until it reached 0 and then the
next arriving thread would get stuck in decrement_counter. Also,
interrupts were not reenabled in all cases.
If mp_process_enable is interrupted after pthread_create, but
before its exit code is examined, the cleanup code may be run
even when pthread_create did not fail, so we need to disable
interrupts in this region.
If a thread is killed while it holds a spinlock, the lock will
never be released, leading to deadlocks. Hence we have to clean
up spinlocks in ECL_WITH_SPINLOCK_END. In mp_process_enable,
other cleanup (deallocating the environment, unlisting the
process) has to performed too.
This is important to prevent race conditions. If interrupts are
left disabled, the environment may be wrongly write protected by
an interrupting thread and completely harmless writes in the
environment can lead to segmentation faults.
If a process, that has already unwound its whole frame stack
(after ECL_CATCH_ALL_END in thread_entry_point) is interrupted by
a call to mp_exit_process, ECL will crash with a segmentation
fault. We thus need to aquire the start_stop_spinlock before we
unwind the frame stack.
If a thread is interrupted while interrupts are disabled by C,
then the signal is queued and the environment is write protected
by mprotect. If another thread then calls queue_signal, it will
try to write in the protected environment, leading to a
segmentation fault. Since mprotect can only protect whole memory
pages, we need to allocate the pending interrupts and the signal
queue in a separate struct.
It didn't wake up all processes to check the condition what caused n+1 lag in
condition check for signal-process (when called with n>1). Fixes#421. No
regression test, because this is already tested in sem-signal-* tests (they were
failing).
bytecompiled functions may not have a name (i.e lambda assigned to
smothing). Recognize that fact, so when we read back such functions
from file we can call bc-compile on them. Fixes#313.