mirror of
https://gitlab.com/embeddable-common-lisp/ecl.git
synced 2025-12-06 02:40:26 -08:00
core: fix a race condition between core symbols and the gc
The GC is enabled when we create initial symbols. The function make_this_symbol initializes symbols from a static table as follows: 1. initialize symbol structure fields 2. associate the symbol with its package 3. associate the symbol with its function 4. increment cl_num_symbols_in_core Most notably in point 2: s->symbol.name = ecl_make_constant_base_string(name,-1); GC's stacks_scanner marks [cl_symbols; cl_symbols+cl_num_symbols_in_core] in other words, if the GC kicks in between 1. and 4., the symbol name may be garbage collected, messing the symbol name and package exports. To mitigate that, we assign intermediate values on the stack and increment the number of symbols in core after the symbol is initialized: 1. store initialization values on stack -- cl_object foo = alloc(); 2. initialize symbol structure fields 3. increment cl_num_symbols_in_core 4. associate the symbol with its package and function
This commit is contained in:
parent
9d8394f0cd
commit
09622435bc
1 changed files with 9 additions and 7 deletions
|
|
@ -206,7 +206,7 @@ make_this_symbol(int i, volatile cl_object s, int code,
|
|||
cl_objectfn fun, int narg, cl_object value)
|
||||
{
|
||||
enum ecl_stype stp;
|
||||
cl_object package;
|
||||
cl_object package, sym_name, sym_cname;
|
||||
bool form = 0;
|
||||
|
||||
switch (code & 3) {
|
||||
|
|
@ -228,6 +228,8 @@ make_this_symbol(int i, volatile cl_object s, int code,
|
|||
case FFI_PACKAGE: package = cl_core.ffi_package; break;
|
||||
default: printf("%d\n", code & ~(int)3); ecl_internal_error("Unknown package code in init_all_symbols()");
|
||||
}
|
||||
sym_name = ecl_make_constant_base_string(name,-1);
|
||||
sym_cname = ecl_cstring_to_base_string_or_nil(cname);
|
||||
s->symbol.t = t_symbol;
|
||||
#ifdef ECL_THREADS
|
||||
s->symbol.binding = ECL_MISSING_SPECIAL_BINDING;
|
||||
|
|
@ -241,16 +243,17 @@ make_this_symbol(int i, volatile cl_object s, int code,
|
|||
s->symbol.hpack = ECL_NIL;
|
||||
s->symbol.stype = stp;
|
||||
s->symbol.hpack = package;
|
||||
s->symbol.name = ecl_make_constant_base_string(name,-1);
|
||||
s->symbol.cname = ecl_cstring_to_base_string_or_nil(cname);
|
||||
s->symbol.name = sym_name;
|
||||
s->symbol.cname = sym_cname;
|
||||
/* Before this statement symbol pointers are not marked by GC. */
|
||||
cl_num_symbols_in_core = i + 1;
|
||||
if (package == cl_core.keyword_package) {
|
||||
package->pack.external =
|
||||
_ecl_sethash(s->symbol.name, package->pack.external, s);
|
||||
package->pack.external = _ecl_sethash(sym_name, package->pack.external, s);
|
||||
ECL_SET(s, s);
|
||||
} else {
|
||||
int intern_flag;
|
||||
ECL_SET(s, value);
|
||||
if (ecl_find_symbol(s->symbol.name, package, &intern_flag) != ECL_NIL
|
||||
if (ecl_find_symbol(sym_name, package, &intern_flag) != ECL_NIL
|
||||
&& intern_flag == ECL_INHERITED) {
|
||||
ecl_shadowing_import(s, package);
|
||||
} else {
|
||||
|
|
@ -279,7 +282,6 @@ make_this_symbol(int i, volatile cl_object s, int code,
|
|||
* narg here. -- mg 2019-12-02 */
|
||||
si_set_symbol_plist(s, cl_list(2, @'call-arguments-limit', ecl_make_fixnum(narg)));
|
||||
#endif
|
||||
cl_num_symbols_in_core = i + 1;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue