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); 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 */ /* Defining EnumProcessModules for openning `self' as an ffi-lib */
@ -161,7 +165,7 @@ END_XFORM_SKIP;
static Scheme_Type ffi_lib_tag; static Scheme_Type ffi_lib_tag;
typedef struct ffi_lib_struct { typedef struct ffi_lib_struct {
Scheme_Object so; Scheme_Object so;
void* handle; NON_GCBALE_PTR(void) handle;
Scheme_Object* name; Scheme_Object* name;
Scheme_Hash_Table* objects; Scheme_Hash_Table* objects;
} ffi_lib_struct; } ffi_lib_struct;
@ -180,14 +184,12 @@ int ffi_lib_SIZE(void *p) {
} }
int ffi_lib_MARK(void *p) { int ffi_lib_MARK(void *p) {
ffi_lib_struct *s = (ffi_lib_struct *)p; ffi_lib_struct *s = (ffi_lib_struct *)p;
gcMARK(s->handle);
gcMARK(s->name); gcMARK(s->name);
gcMARK(s->objects); gcMARK(s->objects);
return gcBYTES_TO_WORDS(sizeof(ffi_lib_struct)); return gcBYTES_TO_WORDS(sizeof(ffi_lib_struct));
} }
int ffi_lib_FIXUP(void *p) { int ffi_lib_FIXUP(void *p) {
ffi_lib_struct *s = (ffi_lib_struct *)p; ffi_lib_struct *s = (ffi_lib_struct *)p;
gcFIXUP(s->handle);
gcFIXUP(s->name); gcFIXUP(s->name);
gcFIXUP(s->objects); gcFIXUP(s->objects);
return gcBYTES_TO_WORDS(sizeof(ffi_lib_struct)); 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; static Scheme_Type ffi_obj_tag;
typedef struct ffi_obj_struct { typedef struct ffi_obj_struct {
Scheme_Object so; Scheme_Object so;
void* obj; NON_GCBALE_PTR(void) obj;
char* name; char* name;
ffi_lib_struct* lib; NON_GCBALE_PTR(ffi_lib_struct) lib;
} ffi_obj_struct; } ffi_obj_struct;
#define SCHEME_FFIOBJP(x) (SCHEME_TYPE(x)==ffi_obj_tag) #define SCHEME_FFIOBJP(x) (SCHEME_TYPE(x)==ffi_obj_tag)
#define MYNAME "ffi-obj?" #define MYNAME "ffi-obj?"
@ -290,16 +292,12 @@ int ffi_obj_SIZE(void *p) {
} }
int ffi_obj_MARK(void *p) { int ffi_obj_MARK(void *p) {
ffi_obj_struct *s = (ffi_obj_struct *)p; ffi_obj_struct *s = (ffi_obj_struct *)p;
gcMARK(s->obj);
gcMARK(s->name); gcMARK(s->name);
gcMARK(s->lib);
return gcBYTES_TO_WORDS(sizeof(ffi_obj_struct)); return gcBYTES_TO_WORDS(sizeof(ffi_obj_struct));
} }
int ffi_obj_FIXUP(void *p) { int ffi_obj_FIXUP(void *p) {
ffi_obj_struct *s = (ffi_obj_struct *)p; ffi_obj_struct *s = (ffi_obj_struct *)p;
gcFIXUP(s->obj);
gcFIXUP(s->name); gcFIXUP(s->name);
gcFIXUP(s->lib);
return gcBYTES_TO_WORDS(sizeof(ffi_obj_struct)); return gcBYTES_TO_WORDS(sizeof(ffi_obj_struct));
} }
END_XFORM_SKIP; 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)) if (SCHEME_FALSEP(sym) || SAME_OBJ(sym, default_sym))
return FFI_DEFAULT_ABI; return FFI_DEFAULT_ABI;
else if (SAME_OBJ(sym, sysv_sym)) { else if (SAME_OBJ(sym, sysv_sym)) {
#if defined(WINDOWS_DYNAMIC_LOAD) && !defined(_WIN64) #ifdef WINDOWS_DYNAMIC_LOAD
return FFI_SYSV; return FFI_SYSV;
#else #else
scheme_signal_error("%s: ABI not implemented: %V", who, sym); scheme_signal_error("%s: ABI not implemented: %V", who, sym);
#endif #endif
} else if (SAME_OBJ(sym, stdcall_sym)) { } else if (SAME_OBJ(sym, stdcall_sym)) {
#if defined(WINDOWS_DYNAMIC_LOAD) && !defined(_WIN64) #ifdef WINDOWS_DYNAMIC_LOAD
return FFI_STDCALL; return FFI_STDCALL;
#else #else
scheme_signal_error("%s: ABI not implemented: %V", who, sym); 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; static Scheme_Type ffi_callback_tag;
typedef struct ffi_callback_struct { typedef struct ffi_callback_struct {
Scheme_Object so; Scheme_Object so;
void* callback; NON_GCBALE_PTR(void) callback;
Scheme_Object* proc; Scheme_Object* proc;
Scheme_Object* itypes; Scheme_Object* itypes;
Scheme_Object* otype; Scheme_Object* otype;
@ -1174,7 +1172,6 @@ int ffi_callback_SIZE(void *p) {
} }
int ffi_callback_MARK(void *p) { int ffi_callback_MARK(void *p) {
ffi_callback_struct *s = (ffi_callback_struct *)p; ffi_callback_struct *s = (ffi_callback_struct *)p;
gcMARK(s->callback);
gcMARK(s->proc); gcMARK(s->proc);
gcMARK(s->itypes); gcMARK(s->itypes);
gcMARK(s->otype); gcMARK(s->otype);
@ -1183,7 +1180,6 @@ int ffi_callback_MARK(void *p) {
} }
int ffi_callback_FIXUP(void *p) { int ffi_callback_FIXUP(void *p) {
ffi_callback_struct *s = (ffi_callback_struct *)p; ffi_callback_struct *s = (ffi_callback_struct *)p;
gcFIXUP(s->callback);
gcFIXUP(s->proc); gcFIXUP(s->proc);
gcFIXUP(s->itypes); gcFIXUP(s->itypes);
gcFIXUP(s->otype); 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); 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 */ /* Defining EnumProcessModules for openning `self' as an ffi-lib */
@ -161,7 +165,7 @@ END_XFORM_SKIP;
/* Library objects */ /* Library objects */
@cdefstruct[ffi-lib @cdefstruct[ffi-lib
[handle "void*"] [handle "NON_GCBALE_PTR(void)"]
[name "Scheme_Object*"] [name "Scheme_Object*"]
[objects "Scheme_Hash_Table*"]] [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 */ /* Pull pointers (mostly functions) out of ffi-lib objects */
@cdefstruct[ffi-obj @cdefstruct[ffi-obj
[obj "void*"] [obj "NON_GCBALE_PTR(void)"]
[name "char*"] [name "char*"]
[lib "ffi_lib_struct*"]] [lib "NON_GCBALE_PTR(ffi_lib_struct)"]]
/* (ffi-obj objname ffi-lib-or-libname) -> ffi-obj */ /* (ffi-obj objname ffi-lib-or-libname) -> ffi-obj */
@cdefine[ffi-obj 2]{ @cdefine[ffi-obj 2]{
@ -972,7 +976,7 @@ ffi_abi sym_to_abi(char *who, Scheme_Object *sym)
/* Callback type */ /* Callback type */
@cdefstruct[ffi-callback @cdefstruct[ffi-callback
[callback "void*"] [callback "NON_GCBALE_PTR(void)"]
[proc "Scheme_Object*"] [proc "Scheme_Object*"]
[itypes "Scheme_Object*"] [itypes "Scheme_Object*"]
[otype "Scheme_Object*"] [otype "Scheme_Object*"]

View File

@ -1222,10 +1222,11 @@ void scheme_reset_finalizations(void)
current_lifetime++; 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; Finalization *fn;
GC_CAN_IGNORE void *data;
if (fns->lifetime != current_lifetime) if (fns->lifetime != current_lifetime)
return; 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) { if (fns->scheme_first->next || fns->ext_f || fns->prim_first) {
/* Re-install low-level finalizer and run a scheme finalizer */ /* Re-install low-level finalizer and run a scheme finalizer */
GC_register_eager_finalizer(o, fns->scheme_first->next ? 1 : 2, 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; fn = fns->scheme_first;
@ -1244,15 +1245,26 @@ static void do_next_finalization(void *o, void *data)
else else
fn->next->prev = NULL; 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; return;
} }
if (fns->ext_f) if (fns->ext_f) {
fns->ext_f(o, fns->ext_data); data = fns->ext_data;
fns->ext_data = NULL;
fns->ext_f(o, data);
}
for (fn = fns->prim_first; fn; fn = fn->next) { for (fn = fns->prim_first; fn; fn = fn->next) {
fn->f(o, fn->data); data = fn->data;
fn->data = NULL;
fn->f(o, data);
} }
} }