fix some GC-related problems
due to pointer fields in GC-allocated structures that do not refer to GC-allocated memory; if the corresponding memory is free()ed and then the GC later takes over the same page of memory, then bad things can happen; some of the problems were crashing the Windows port while running the 2htdp image tests
This commit is contained in:
parent
f557707764
commit
3b4a1c4e94
|
@ -84,6 +84,10 @@
|
|||
|
||||
static void save_errno_values(int kind);
|
||||
|
||||
/* This make hides pointerness from cdefstruct so that it
|
||||
doesn't generate a mark/fixup action: */
|
||||
#define NON_GCBALE_PTR(t) t*
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Defining EnumProcessModules for openning `self' as an ffi-lib */
|
||||
|
||||
|
@ -161,7 +165,7 @@ END_XFORM_SKIP;
|
|||
static Scheme_Type ffi_lib_tag;
|
||||
typedef struct ffi_lib_struct {
|
||||
Scheme_Object so;
|
||||
void* handle;
|
||||
NON_GCBALE_PTR(void) handle;
|
||||
Scheme_Object* name;
|
||||
Scheme_Hash_Table* objects;
|
||||
} ffi_lib_struct;
|
||||
|
@ -180,14 +184,12 @@ int ffi_lib_SIZE(void *p) {
|
|||
}
|
||||
int ffi_lib_MARK(void *p) {
|
||||
ffi_lib_struct *s = (ffi_lib_struct *)p;
|
||||
gcMARK(s->handle);
|
||||
gcMARK(s->name);
|
||||
gcMARK(s->objects);
|
||||
return gcBYTES_TO_WORDS(sizeof(ffi_lib_struct));
|
||||
}
|
||||
int ffi_lib_FIXUP(void *p) {
|
||||
ffi_lib_struct *s = (ffi_lib_struct *)p;
|
||||
gcFIXUP(s->handle);
|
||||
gcFIXUP(s->name);
|
||||
gcFIXUP(s->objects);
|
||||
return gcBYTES_TO_WORDS(sizeof(ffi_lib_struct));
|
||||
|
@ -271,9 +273,9 @@ static Scheme_Object *foreign_ffi_lib_name(int argc, Scheme_Object *argv[])
|
|||
static Scheme_Type ffi_obj_tag;
|
||||
typedef struct ffi_obj_struct {
|
||||
Scheme_Object so;
|
||||
void* obj;
|
||||
NON_GCBALE_PTR(void) obj;
|
||||
char* name;
|
||||
ffi_lib_struct* lib;
|
||||
NON_GCBALE_PTR(ffi_lib_struct) lib;
|
||||
} ffi_obj_struct;
|
||||
#define SCHEME_FFIOBJP(x) (SCHEME_TYPE(x)==ffi_obj_tag)
|
||||
#define MYNAME "ffi-obj?"
|
||||
|
@ -290,16 +292,12 @@ int ffi_obj_SIZE(void *p) {
|
|||
}
|
||||
int ffi_obj_MARK(void *p) {
|
||||
ffi_obj_struct *s = (ffi_obj_struct *)p;
|
||||
gcMARK(s->obj);
|
||||
gcMARK(s->name);
|
||||
gcMARK(s->lib);
|
||||
return gcBYTES_TO_WORDS(sizeof(ffi_obj_struct));
|
||||
}
|
||||
int ffi_obj_FIXUP(void *p) {
|
||||
ffi_obj_struct *s = (ffi_obj_struct *)p;
|
||||
gcFIXUP(s->obj);
|
||||
gcFIXUP(s->name);
|
||||
gcFIXUP(s->lib);
|
||||
return gcBYTES_TO_WORDS(sizeof(ffi_obj_struct));
|
||||
}
|
||||
END_XFORM_SKIP;
|
||||
|
@ -1049,13 +1047,13 @@ ffi_abi sym_to_abi(char *who, Scheme_Object *sym)
|
|||
if (SCHEME_FALSEP(sym) || SAME_OBJ(sym, default_sym))
|
||||
return FFI_DEFAULT_ABI;
|
||||
else if (SAME_OBJ(sym, sysv_sym)) {
|
||||
#if defined(WINDOWS_DYNAMIC_LOAD) && !defined(_WIN64)
|
||||
#ifdef WINDOWS_DYNAMIC_LOAD
|
||||
return FFI_SYSV;
|
||||
#else
|
||||
scheme_signal_error("%s: ABI not implemented: %V", who, sym);
|
||||
#endif
|
||||
} else if (SAME_OBJ(sym, stdcall_sym)) {
|
||||
#if defined(WINDOWS_DYNAMIC_LOAD) && !defined(_WIN64)
|
||||
#ifdef WINDOWS_DYNAMIC_LOAD
|
||||
return FFI_STDCALL;
|
||||
#else
|
||||
scheme_signal_error("%s: ABI not implemented: %V", who, sym);
|
||||
|
@ -1153,7 +1151,7 @@ static Scheme_Object *foreign_make_cstruct_type(int argc, Scheme_Object *argv[])
|
|||
static Scheme_Type ffi_callback_tag;
|
||||
typedef struct ffi_callback_struct {
|
||||
Scheme_Object so;
|
||||
void* callback;
|
||||
NON_GCBALE_PTR(void) callback;
|
||||
Scheme_Object* proc;
|
||||
Scheme_Object* itypes;
|
||||
Scheme_Object* otype;
|
||||
|
@ -1174,7 +1172,6 @@ int ffi_callback_SIZE(void *p) {
|
|||
}
|
||||
int ffi_callback_MARK(void *p) {
|
||||
ffi_callback_struct *s = (ffi_callback_struct *)p;
|
||||
gcMARK(s->callback);
|
||||
gcMARK(s->proc);
|
||||
gcMARK(s->itypes);
|
||||
gcMARK(s->otype);
|
||||
|
@ -1183,7 +1180,6 @@ int ffi_callback_MARK(void *p) {
|
|||
}
|
||||
int ffi_callback_FIXUP(void *p) {
|
||||
ffi_callback_struct *s = (ffi_callback_struct *)p;
|
||||
gcFIXUP(s->callback);
|
||||
gcFIXUP(s->proc);
|
||||
gcFIXUP(s->itypes);
|
||||
gcFIXUP(s->otype);
|
||||
|
|
|
@ -87,6 +87,10 @@ exec racket "$0" > `echo "$0" | sed 's/rktc$/c/'` "$0"
|
|||
|
||||
static void save_errno_values(int kind);
|
||||
|
||||
/* This make hides pointerness from cdefstruct so that it
|
||||
doesn't generate a mark/fixup action: */
|
||||
#define NON_GCBALE_PTR(t) t*
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Defining EnumProcessModules for openning `self' as an ffi-lib */
|
||||
|
||||
|
@ -161,7 +165,7 @@ END_XFORM_SKIP;
|
|||
/* Library objects */
|
||||
|
||||
@cdefstruct[ffi-lib
|
||||
[handle "void*"]
|
||||
[handle "NON_GCBALE_PTR(void)"]
|
||||
[name "Scheme_Object*"]
|
||||
[objects "Scheme_Hash_Table*"]]
|
||||
|
||||
|
@ -228,9 +232,9 @@ THREAD_LOCAL_DECL(static Scheme_Hash_Table *opened_libs);
|
|||
/* Pull pointers (mostly functions) out of ffi-lib objects */
|
||||
|
||||
@cdefstruct[ffi-obj
|
||||
[obj "void*"]
|
||||
[obj "NON_GCBALE_PTR(void)"]
|
||||
[name "char*"]
|
||||
[lib "ffi_lib_struct*"]]
|
||||
[lib "NON_GCBALE_PTR(ffi_lib_struct)"]]
|
||||
|
||||
/* (ffi-obj objname ffi-lib-or-libname) -> ffi-obj */
|
||||
@cdefine[ffi-obj 2]{
|
||||
|
@ -972,7 +976,7 @@ ffi_abi sym_to_abi(char *who, Scheme_Object *sym)
|
|||
/* Callback type */
|
||||
|
||||
@cdefstruct[ffi-callback
|
||||
[callback "void*"]
|
||||
[callback "NON_GCBALE_PTR(void)"]
|
||||
[proc "Scheme_Object*"]
|
||||
[itypes "Scheme_Object*"]
|
||||
[otype "Scheme_Object*"]
|
||||
|
|
|
@ -1222,10 +1222,11 @@ void scheme_reset_finalizations(void)
|
|||
current_lifetime++;
|
||||
}
|
||||
|
||||
static void do_next_finalization(void *o, void *data)
|
||||
static void do_next_finalization(void *o, void *_data)
|
||||
{
|
||||
Finalizations *fns = *(Finalizations **)data;
|
||||
Finalizations *fns = *(Finalizations **)_data;
|
||||
Finalization *fn;
|
||||
GC_CAN_IGNORE void *data;
|
||||
|
||||
if (fns->lifetime != current_lifetime)
|
||||
return;
|
||||
|
@ -1234,7 +1235,7 @@ static void do_next_finalization(void *o, void *data)
|
|||
if (fns->scheme_first->next || fns->ext_f || fns->prim_first) {
|
||||
/* Re-install low-level finalizer and run a scheme finalizer */
|
||||
GC_register_eager_finalizer(o, fns->scheme_first->next ? 1 : 2,
|
||||
do_next_finalization, data, NULL, NULL);
|
||||
do_next_finalization, _data, NULL, NULL);
|
||||
}
|
||||
|
||||
fn = fns->scheme_first;
|
||||
|
@ -1244,15 +1245,26 @@ static void do_next_finalization(void *o, void *data)
|
|||
else
|
||||
fn->next->prev = NULL;
|
||||
|
||||
fn->f(o, fn->data);
|
||||
/* Clear out the `data' pointer, in case it refers to
|
||||
memory that is free()ed, in which case the GC might
|
||||
later take over the same page of memory. */
|
||||
data = fn->data;
|
||||
fn->data = NULL;
|
||||
|
||||
fn->f(o, data);
|
||||
return;
|
||||
}
|
||||
|
||||
if (fns->ext_f)
|
||||
fns->ext_f(o, fns->ext_data);
|
||||
if (fns->ext_f) {
|
||||
data = fns->ext_data;
|
||||
fns->ext_data = NULL;
|
||||
fns->ext_f(o, data);
|
||||
}
|
||||
|
||||
for (fn = fns->prim_first; fn; fn = fn->next) {
|
||||
fn->f(o, fn->data);
|
||||
data = fn->data;
|
||||
fn->data = NULL;
|
||||
fn->f(o, data);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user