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.
When mp_process_interrupt and thread_cleanup are called at the same
time, it is possible that the thread-local environment is deallocated
while ecl_interrupt_process tries to use it. This two methods thus
need to be protected with a lock.
si_set_finalizer is CL-world function and returns 0 values. That means
in particular, that env->nvalues is changed.
In this situation, when new binding was introduced, we could lose our
nvalues, what lead to invalid multiple-value-bind (next commit will
contain a regression test).
We use unprotected version. If interrupts cause problems with it, we
may need to wrap it in disable_interrupts. Threading code uses
ecl_set_finalizer_unprotected without such wrapping though, so I
believe that should be safe.
Fixes#233.
These two function are the same.
Here is my understanding: FEprogram_error_noreturn was introduced with
the noreturn function attribute in commit 7d9fb8bb because
FEprogram_error did not have this attribute. However, FEprogram_error
got the noreturn function attribute in commit 790d466c. Now there is
no reason to have both of these.
This removes FEprogram_error_noreturn and changes all calls to it
with calls to FEprogram_error instead.
This is for signalling an error about binding a constant variable.
This makes the error messages originally in commits 745686, c9e732
and 4e3283 more precise.
PROGV was allowed to bind constants in the C-compiler and the bytecode
compiler and interpreter, but the behavior would differ between them:
> (defun foo ()
(flet ((memq (item list) (member item list :test #'eq)))
(progv (list :test) (list :test-not)
(memq 'bar '(bar baz quux)))))
FOO
> (foo)
(BAZ QUUX)
> (compile 'foo)
FOO
> (foo)
(BAR BAZ QUUX)
CLHS says the behavior is undefined when attempting to bind or assign
constant variables (CLHS 3.1.2.1.1.3 and the entry for defconstant).
The C-compiler and bytecode compiler and interpreter give errors when
attempting to bind or assign constant variables in lambda expressions,
LET, SETQ and various other binding/assignment forms. So the behavior
above in PROGV is inconsistent.
Now give an error when attempting to bind a constant variable in PROGV
in the C-compiler and the bytecode compiler and interpreter.
M-V-B was allowed to lexically and dynamically bind constants in the
bytecode compiler and interpreter:
> (multiple-value-bind (pi rem) (truncate pi) pi)
3
CLHS says the behavior is undefined when attempting to bind or assign
constant variables (CLHS 3.1.2.1.1.3 and the entry for defconstant).
The C-compiler gives errors for these sorts of things, and the bytecode
compiler and interpreter gives errors when attempting to bind or assign
constant variables in lambda expressions, LET, SETQ and various other
binding/assignment forms. So the behavior above in M-V-B is
inconsistent with the C-compiler and other parts of the bytecode
compiler and interpreter.
Now give an error when attempting to bind a constant variable in M-V-B
in the bytecode compiler and interpreter.
LET/LET* were allowed to lexically and dynamically bind constants in
the bytecode compiler and interpreter:
> (let ((pi 3)) pi)
3
> (progn (defconstant +c+ 'foo) (let ((+c+ 'bar)) +c+))
BAR
> (flet ((hello () (format t "hi")))
(let ((t nil))
(declare (special t))
; Oops, now this returns a string
(hello)))
"hi"
Plus plenty of other ways to wreak havoc on unsuspecting code.
CLHS says the behavior is undefined when attempting to bind or assign
constant variables (CLHS 3.1.2.1.1.3 and the entry for defconstant).
(Well, CLHS 3.4.1 explicitly says that constant variables cannot be
used for variables in lambda lists.)
The C-compiler gives errors for these sorts of things, and the bytecode
compiler and interpreter gives errors when attempting to bind or assign
constant variables in lambda expressions, SETQ and various other forms.
So the behavior above in LET is inconsistent with both the C-compiler
and other parts of the bytecode compiler and interpreter.
Now give an error when attempting to bind a constant variable in
LET/LET* in the bytecode compiler and interpreter.
This also changes the behavior of PROG/PROG* and DESTRUCTURING-BIND so
that they give errors when attempting to bind constants as well.
PROGV was attempting to bind whatever was in its variable list
without checking its type. Using either the C-compiler or bytecode
compiler/interpreter, the following example would lead to a segfault
on my OpenBSD and Linux boxes:
> (defun foo () (progv (list 3) (list 3)))
FOO
> (foo)
Condition of type: SEGMENTATION-VIOLATION
[...]
Now give an error when attempting to bind something that is not a
symbol in PROGV (in both the C-compiler and bytecode compiler and
interpreter).
The contents of an uninitialized variable was used when setting the
TCP_NODELAY option for sockets created with open-client-stream and
open-server-stream, so this option would not be set when the value
of the variable happened to be 0 (which happened regularly on my
OpenBSD box).
Tested on OpenBSD and Linux.
This header needs to be included so the TCP_* defines are available.
Sockets created with open-client-stream and open-server-stream would
try to set TCP_NODELAY if available, but they couldn't because this
was not defined.
Tested on OpenBSD and Linux.