From 01ae0fbf30b74e2490144fceabbf5bc5d96f1ba7 Mon Sep 17 00:00:00 2001 From: Daniel Colascione Date: Wed, 2 Apr 2014 17:18:08 -0700 Subject: Add GC bug investigation code --- src/alloc.c | 105 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) (limited to 'src/alloc.c') diff --git a/src/alloc.c b/src/alloc.c index e5cd5fed4e3..8ec0421e7a4 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -48,6 +48,10 @@ along with GNU Emacs. If not, see . */ #include +#ifdef HAVE_EXECINFO_H +#include /* For backtrace */ +#endif + #if (defined ENABLE_CHECKING \ && defined HAVE_VALGRIND_VALGRIND_H \ && !defined USE_VALGRIND) @@ -192,6 +196,36 @@ static ptrdiff_t pure_bytes_used_non_lisp; const char *pending_malloc_warning; +#if 0 /* Normally, pointer sanity only on request... */ +#ifdef ENABLE_CHECKING +#define SUSPICIOUS_OBJECT_CHECKING 1 +#endif +#endif + +/* ... but unconditionally use SUSPICIOUS_OBJECT_CHECKING while the GC + bug is unresolved. */ +#define SUSPICIOUS_OBJECT_CHECKING 1 + +#ifdef SUSPICIOUS_OBJECT_CHECKING +struct suspicious_free_record { + void* suspicious_object; +#ifdef HAVE_EXECINFO_H + void* backtrace[128]; +#endif +}; +static void* suspicious_objects[32]; +static int suspicious_object_index; +struct suspicious_free_record suspicious_free_history[64]; +static int suspicious_free_history_index; +/* Find the first currently-monitored suspicious pointer in range + [begin,end) or NULL if no such pointer exists. */ +static void* find_suspicious_object_in_range (void* begin, void* end); +static void detect_suspicious_free (void* ptr); +#else +#define find_suspicious_object_in_range(begin, end) NULL +#define detect_suspicious_free(ptr) (void) +#endif + /* Maximum amount of C stack to save when a GC happens. */ #ifndef MAX_SAVE_STACK @@ -2922,6 +2956,7 @@ vector_nbytes (struct Lisp_Vector *v) static void cleanup_vector (struct Lisp_Vector *vector) { + detect_suspicious_free (vector); if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_FONT) && ((vector->header.size & PSEUDOVECTOR_SIZE_MASK) == FONT_OBJECT_MAX)) @@ -3081,6 +3116,9 @@ allocate_vectorlike (ptrdiff_t len) mallopt (M_MMAP_MAX, MMAP_MAX_AREAS); #endif + if (find_suspicious_object_in_range (p, (char*)p + nbytes)) + emacs_abort (); + consing_since_gc += nbytes; vector_cells_consed += len; } @@ -3780,6 +3818,7 @@ refill_memory_reserve (void) Vmemory_full = Qnil; #endif } + /************************************************************************ C Stack Marking @@ -6787,6 +6826,71 @@ which_symbols (Lisp_Object obj, EMACS_INT find_max) return found; } +#ifdef SUSPICIOUS_OBJECT_CHECKING + +static void* +find_suspicious_object_in_range (void* begin, void* end) +{ + char* begin_a = begin; + char* end_a = end; + int i; + + for (i = 0; i < EARRAYSIZE (suspicious_objects); ++i) { + char* suspicious_object = suspicious_objects[i]; + if (begin_a <= suspicious_object && suspicious_object < end_a) + return suspicious_object; + } + + return NULL; +} + +static void +detect_suspicious_free (void* ptr) +{ + int i; + struct suspicious_free_record* rec; + + eassert (ptr != NULL); + + for (i = 0; i < EARRAYSIZE (suspicious_objects); ++i) + if (suspicious_objects[i] == ptr) + { + rec = &suspicious_free_history[suspicious_free_history_index++]; + if (suspicious_free_history_index == + EARRAYSIZE (suspicious_free_history)) + { + suspicious_free_history_index = 0; + } + + memset (rec, 0, sizeof (rec)); + rec->suspicious_object = ptr; +#ifdef HAVE_EXECINFO_H + backtrace (&rec->backtrace[0], EARRAYSIZE (rec->backtrace)); +#endif + suspicious_objects[i] = NULL; + } +} + +#endif /* SUSPICIOUS_OBJECT_CHECKING */ + +DEFUN ("suspicious-object", Fsuspicious_object, Ssuspicious_object, 1, 1, 0, + doc: /* Return OBJ, maybe marking it for extra scrutiny. +If Emacs is compiled with suspicous object checking, capture +a stack trace when OBJ is freed in order to help track down +garbage collection bugs. Otherwise, do nothing and return OBJ. */) + (Lisp_Object obj) +{ +#ifdef SUSPICIOUS_OBJECT_CHECKING + /* Right now, we care only about vectors. */ + if (VECTORLIKEP (obj)) { + suspicious_objects[suspicious_object_index++] = XVECTOR (obj); + if (suspicious_object_index == EARRAYSIZE (suspicious_objects)) + suspicious_object_index = 0; + } +#endif + return obj; +} + #ifdef ENABLE_CHECKING bool suppress_checking; @@ -6957,6 +7061,7 @@ The time is in seconds as a floating point value. */); defsubr (&Sgarbage_collect); defsubr (&Smemory_limit); defsubr (&Smemory_use_counts); + defsubr (&Ssuspicious_object); #if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES defsubr (&Sgc_status); -- cgit v1.2.1