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:
Matthew Flatt 2010-12-14 05:49:41 -07:00
parent f557707764
commit 3b4a1c4e94
3 changed files with 37 additions and 25 deletions

View File

@ -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);

View File

@ -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*"]

View File

@ -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);
}
}