diff options
| author | Daniel Colascione | 2014-04-02 17:18:08 -0700 |
|---|---|---|
| committer | Daniel Colascione | 2014-04-02 17:18:08 -0700 |
| commit | 01ae0fbf30b74e2490144fceabbf5bc5d96f1ba7 (patch) | |
| tree | 59ca8d7de3510d720153f1cc2d368bd145f21f48 /src | |
| parent | 4fd68bf6cc1dce6c95001fbbac95cef32c86359d (diff) | |
| download | emacs-01ae0fbf30b74e2490144fceabbf5bc5d96f1ba7.tar.gz emacs-01ae0fbf30b74e2490144fceabbf5bc5d96f1ba7.zip | |
Add GC bug investigation code
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 7 | ||||
| -rw-r--r-- | src/alloc.c | 105 | ||||
| -rw-r--r-- | src/data.c | 5 | ||||
| -rw-r--r-- | src/lisp.h | 3 |
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 @@ | |||
| 1 | 2014-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 | |||
| 1 | 2014-04-02 Martin Rudalics <rudalics@gmx.at> | 8 | 2014-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 | ||
| 193 | const char *pending_malloc_warning; | 197 | const 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 | ||
| 210 | struct suspicious_free_record { | ||
| 211 | void* suspicious_object; | ||
| 212 | #ifdef HAVE_EXECINFO_H | ||
| 213 | void* backtrace[128]; | ||
| 214 | #endif | ||
| 215 | }; | ||
| 216 | static void* suspicious_objects[32]; | ||
| 217 | static int suspicious_object_index; | ||
| 218 | struct suspicious_free_record suspicious_free_history[64]; | ||
| 219 | static 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. */ | ||
| 222 | static void* find_suspicious_object_in_range (void* begin, void* end); | ||
| 223 | static 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) | |||
| 2922 | static void | 2956 | static void |
| 2923 | cleanup_vector (struct Lisp_Vector *vector) | 2957 | cleanup_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 | |||
| 6831 | static void* | ||
| 6832 | find_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 | |||
| 6847 | static void | ||
| 6848 | detect_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 | |||
| 6876 | DEFUN ("suspicious-object", Fsuspicious_object, Ssuspicious_object, 1, 1, 0, | ||
| 6877 | doc: /* Return OBJ, maybe marking it for extra scrutiny. | ||
| 6878 | If Emacs is compiled with suspicous object checking, capture | ||
| 6879 | a stack trace when OBJ is freed in order to help track down | ||
| 6880 | garbage 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 | ||
| 6792 | bool suppress_checking; | 6896 | bool 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 |