aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDaniel Colascione2014-04-02 17:18:08 -0700
committerDaniel Colascione2014-04-02 17:18:08 -0700
commit01ae0fbf30b74e2490144fceabbf5bc5d96f1ba7 (patch)
tree59ca8d7de3510d720153f1cc2d368bd145f21f48 /src
parent4fd68bf6cc1dce6c95001fbbac95cef32c86359d (diff)
downloademacs-01ae0fbf30b74e2490144fceabbf5bc5d96f1ba7.tar.gz
emacs-01ae0fbf30b74e2490144fceabbf5bc5d96f1ba7.zip
Add GC bug investigation code
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog7
-rw-r--r--src/alloc.c105
-rw-r--r--src/data.c5
-rw-r--r--src/lisp.h3
4 files changed, 120 insertions, 0 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 22b15a5b00f..1da08defc39 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,10 @@
12014-04-03 Daniel Colascione <dancol@dancol.org>
2
3 * data.c (Ffset): Abort if we're trying to set a function call to
4 a dead lisp object.
5
6 * lisp.h (EARRAYSIZE): New macro.
7
12014-04-02 Martin Rudalics <rudalics@gmx.at> 82014-04-02 Martin Rudalics <rudalics@gmx.at>
2 9
3 * xterm.c (x_new_font): Don't calculate non-toolkit scrollbar 10 * xterm.c (x_new_font): Don't calculate non-toolkit scrollbar
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 <http://www.gnu.org/licenses/>. */
48 48
49#include <verify.h> 49#include <verify.h>
50 50
51#ifdef HAVE_EXECINFO_H
52#include <execinfo.h> /* For backtrace */
53#endif
54
51#if (defined ENABLE_CHECKING \ 55#if (defined ENABLE_CHECKING \
52 && defined HAVE_VALGRIND_VALGRIND_H \ 56 && defined HAVE_VALGRIND_VALGRIND_H \
53 && !defined USE_VALGRIND) 57 && !defined USE_VALGRIND)
@@ -192,6 +196,36 @@ static ptrdiff_t pure_bytes_used_non_lisp;
192 196
193const char *pending_malloc_warning; 197const char *pending_malloc_warning;
194 198
199#if 0 /* Normally, pointer sanity only on request... */
200#ifdef ENABLE_CHECKING
201#define SUSPICIOUS_OBJECT_CHECKING 1
202#endif
203#endif
204
205/* ... but unconditionally use SUSPICIOUS_OBJECT_CHECKING while the GC
206 bug is unresolved. */
207#define SUSPICIOUS_OBJECT_CHECKING 1
208
209#ifdef SUSPICIOUS_OBJECT_CHECKING
210struct suspicious_free_record {
211 void* suspicious_object;
212#ifdef HAVE_EXECINFO_H
213 void* backtrace[128];
214#endif
215};
216static void* suspicious_objects[32];
217static int suspicious_object_index;
218struct suspicious_free_record suspicious_free_history[64];
219static int suspicious_free_history_index;
220/* Find the first currently-monitored suspicious pointer in range
221 [begin,end) or NULL if no such pointer exists. */
222static void* find_suspicious_object_in_range (void* begin, void* end);
223static void detect_suspicious_free (void* ptr);
224#else
225#define find_suspicious_object_in_range(begin, end) NULL
226#define detect_suspicious_free(ptr) (void)
227#endif
228
195/* Maximum amount of C stack to save when a GC happens. */ 229/* Maximum amount of C stack to save when a GC happens. */
196 230
197#ifndef MAX_SAVE_STACK 231#ifndef MAX_SAVE_STACK
@@ -2922,6 +2956,7 @@ vector_nbytes (struct Lisp_Vector *v)
2922static void 2956static void
2923cleanup_vector (struct Lisp_Vector *vector) 2957cleanup_vector (struct Lisp_Vector *vector)
2924{ 2958{
2959 detect_suspicious_free (vector);
2925 if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_FONT) 2960 if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_FONT)
2926 && ((vector->header.size & PSEUDOVECTOR_SIZE_MASK) 2961 && ((vector->header.size & PSEUDOVECTOR_SIZE_MASK)
2927 == FONT_OBJECT_MAX)) 2962 == FONT_OBJECT_MAX))
@@ -3081,6 +3116,9 @@ allocate_vectorlike (ptrdiff_t len)
3081 mallopt (M_MMAP_MAX, MMAP_MAX_AREAS); 3116 mallopt (M_MMAP_MAX, MMAP_MAX_AREAS);
3082#endif 3117#endif
3083 3118
3119 if (find_suspicious_object_in_range (p, (char*)p + nbytes))
3120 emacs_abort ();
3121
3084 consing_since_gc += nbytes; 3122 consing_since_gc += nbytes;
3085 vector_cells_consed += len; 3123 vector_cells_consed += len;
3086 } 3124 }
@@ -3780,6 +3818,7 @@ refill_memory_reserve (void)
3780 Vmemory_full = Qnil; 3818 Vmemory_full = Qnil;
3781#endif 3819#endif
3782} 3820}
3821
3783 3822
3784/************************************************************************ 3823/************************************************************************
3785 C Stack Marking 3824 C Stack Marking
@@ -6787,6 +6826,71 @@ which_symbols (Lisp_Object obj, EMACS_INT find_max)
6787 return found; 6826 return found;
6788} 6827}
6789 6828
6829#ifdef SUSPICIOUS_OBJECT_CHECKING
6830
6831static void*
6832find_suspicious_object_in_range (void* begin, void* end)
6833{
6834 char* begin_a = begin;
6835 char* end_a = end;
6836 int i;
6837
6838 for (i = 0; i < EARRAYSIZE (suspicious_objects); ++i) {
6839 char* suspicious_object = suspicious_objects[i];
6840 if (begin_a <= suspicious_object && suspicious_object < end_a)
6841 return suspicious_object;
6842 }
6843
6844 return NULL;
6845}
6846
6847static void
6848detect_suspicious_free (void* ptr)
6849{
6850 int i;
6851 struct suspicious_free_record* rec;
6852
6853 eassert (ptr != NULL);
6854
6855 for (i = 0; i < EARRAYSIZE (suspicious_objects); ++i)
6856 if (suspicious_objects[i] == ptr)
6857 {
6858 rec = &suspicious_free_history[suspicious_free_history_index++];
6859 if (suspicious_free_history_index ==
6860 EARRAYSIZE (suspicious_free_history))
6861 {
6862 suspicious_free_history_index = 0;
6863 }
6864
6865 memset (rec, 0, sizeof (rec));
6866 rec->suspicious_object = ptr;
6867#ifdef HAVE_EXECINFO_H
6868 backtrace (&rec->backtrace[0], EARRAYSIZE (rec->backtrace));
6869#endif
6870 suspicious_objects[i] = NULL;
6871 }
6872}
6873
6874#endif /* SUSPICIOUS_OBJECT_CHECKING */
6875
6876DEFUN ("suspicious-object", Fsuspicious_object, Ssuspicious_object, 1, 1, 0,
6877 doc: /* Return OBJ, maybe marking it for extra scrutiny.
6878If Emacs is compiled with suspicous object checking, capture
6879a stack trace when OBJ is freed in order to help track down
6880garbage collection bugs. Otherwise, do nothing and return OBJ. */)
6881 (Lisp_Object obj)
6882{
6883#ifdef SUSPICIOUS_OBJECT_CHECKING
6884 /* Right now, we care only about vectors. */
6885 if (VECTORLIKEP (obj)) {
6886 suspicious_objects[suspicious_object_index++] = XVECTOR (obj);
6887 if (suspicious_object_index == EARRAYSIZE (suspicious_objects))
6888 suspicious_object_index = 0;
6889 }
6890#endif
6891 return obj;
6892}
6893
6790#ifdef ENABLE_CHECKING 6894#ifdef ENABLE_CHECKING
6791 6895
6792bool suppress_checking; 6896bool suppress_checking;
@@ -6957,6 +7061,7 @@ The time is in seconds as a floating point value. */);
6957 defsubr (&Sgarbage_collect); 7061 defsubr (&Sgarbage_collect);
6958 defsubr (&Smemory_limit); 7062 defsubr (&Smemory_limit);
6959 defsubr (&Smemory_use_counts); 7063 defsubr (&Smemory_use_counts);
7064 defsubr (&Ssuspicious_object);
6960 7065
6961#if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES 7066#if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES
6962 defsubr (&Sgc_status); 7067 defsubr (&Sgc_status);
diff --git a/src/data.c b/src/data.c
index 4ef81f2474e..dd220987fd7 100644
--- a/src/data.c
+++ b/src/data.c
@@ -727,6 +727,11 @@ DEFUN ("fset", Ffset, Sfset, 2, 2, 0,
727 if (AUTOLOADP (function)) 727 if (AUTOLOADP (function))
728 Fput (symbol, Qautoload, XCDR (function)); 728 Fput (symbol, Qautoload, XCDR (function));
729 729
730 /* Convert to eassert or remove after GC bug is found. In the
731 meantime, check unconditionally, at a slight perf hit. */
732 if (valid_lisp_object_p (definition) < 1)
733 emacs_abort ();
734
730 set_symbol_function (symbol, definition); 735 set_symbol_function (symbol, definition);
731 736
732 return definition; 737 return definition;
diff --git a/src/lisp.h b/src/lisp.h
index f8b5384ceb0..b8c909ab60d 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -58,6 +58,9 @@ INLINE_HEADER_BEGIN
58#define max(a, b) ((a) > (b) ? (a) : (b)) 58#define max(a, b) ((a) > (b) ? (a) : (b))
59#define min(a, b) ((a) < (b) ? (a) : (b)) 59#define min(a, b) ((a) < (b) ? (a) : (b))
60 60
61/* Find number of elements in array */
62#define EARRAYSIZE(arr) (sizeof (arr) / sizeof ((arr)[0]))
63
61/* EMACS_INT - signed integer wide enough to hold an Emacs value 64/* EMACS_INT - signed integer wide enough to hold an Emacs value
62 EMACS_INT_MAX - maximum value of EMACS_INT; can be used in #if 65 EMACS_INT_MAX - maximum value of EMACS_INT; can be used in #if
63 pI - printf length modifier for EMACS_INT 66 pI - printf length modifier for EMACS_INT