+2011-03-13 Ivan Maidanski <ivmai@mail.ru>
+
+ * dbg_mlc.c (GC_make_closure): Fix SEGV in case GC_malloc returns
+ NULL.
+ * dbg_mlc.c (GC_debug_register_finalizer,
+ GC_debug_register_finalizer_no_order,
+ GC_debug_register_finalizer_unreachable,
+ GC_debug_register_finalizer_ignore_self): Handle out of memory
+ case properly (similar to GC_register_finalizer_inner).
+ * headers.c (GC_install_header): Handle the case when alloc_hdr()
+ returns NULL.
+ * os_dep.c (GC_get_maps_len): Defend against missing "maps" file.
+ * pthread_support.c (GC_mark_thread): Place a dummy return
+ statement (which uses "id" argument) before the actual use of "id"
+ as an array index (to suppress a warning produced by some static
+ code analysis tools).
+ * win32_threads.c (GC_mark_thread): Ditto.
+ * pthread_support.c (GC_thr_init): Abort (with the appropriate
+ message) if out of memory.
+
2011-03-13 Ivan Maidanski <ivmai@mail.ru>
* finalize.c (GC_register_finalizer_inner): Fix a typo in a
/* Returns 1 on success, 0 if source couldn't be determined. */
/* Dest can be any address within a heap object. */
GC_API GC_ref_kind GC_CALL GC_get_back_ptr_info(void *dest, void **base_p,
- size_t *offset_p)
+ size_t *offset_p)
{
oh * hdr = (oh *)GC_base(dest);
ptr_t bp;
ptr_t base = GC_base(p);
GC_ASSERT((ptr_t)p - (ptr_t)base == sizeof(oh));
# ifndef SHORT_DBG_HDRS
- /* Invalidate size */
- ((oh *)base) -> oh_sz = GC_size(base);
+ /* Invalidate size */
+ ((oh *)base) -> oh_sz = GC_size(base);
# endif
GC_free_inner(base);
}
# else
(struct closure *) GC_malloc(sizeof (struct closure));
# endif
-
- result -> cl_fn = fn;
- result -> cl_data = data;
+ if (result != 0) {
+ result -> cl_fn = fn;
+ result -> cl_data = data;
+ }
return((void *)result);
}
if (0 == fn) {
GC_register_finalizer(base, 0, 0, &my_old_fn, &my_old_cd);
} else {
+ cd = GC_make_closure(fn, cd);
+ if (cd == 0) return; /* out of memory */
GC_register_finalizer(base, GC_debug_invoke_finalizer,
- GC_make_closure(fn,cd), &my_old_fn, &my_old_cd);
+ cd, &my_old_fn, &my_old_cd);
}
store_old(obj, my_old_fn, (struct closure *)my_old_cd, ofn, ocd);
}
if (0 == fn) {
GC_register_finalizer_no_order(base, 0, 0, &my_old_fn, &my_old_cd);
} else {
+ cd = GC_make_closure(fn, cd);
+ if (cd == 0) return; /* out of memory */
GC_register_finalizer_no_order(base, GC_debug_invoke_finalizer,
- GC_make_closure(fn,cd), &my_old_fn,
- &my_old_cd);
+ cd, &my_old_fn, &my_old_cd);
}
store_old(obj, my_old_fn, (struct closure *)my_old_cd, ofn, ocd);
}
if (0 == fn) {
GC_register_finalizer_unreachable(base, 0, 0, &my_old_fn, &my_old_cd);
} else {
+ cd = GC_make_closure(fn, cd);
+ if (cd == 0) return; /* out of memory */
GC_register_finalizer_unreachable(base, GC_debug_invoke_finalizer,
- GC_make_closure(fn,cd), &my_old_fn,
- &my_old_cd);
+ cd, &my_old_fn, &my_old_cd);
}
store_old(obj, my_old_fn, (struct closure *)my_old_cd, ofn, ocd);
}
if (0 == fn) {
GC_register_finalizer_ignore_self(base, 0, 0, &my_old_fn, &my_old_cd);
} else {
+ cd = GC_make_closure(fn, cd);
+ if (cd == 0) return; /* out of memory */
GC_register_finalizer_ignore_self(base, GC_debug_invoke_finalizer,
- GC_make_closure(fn,cd), &my_old_fn,
- &my_old_cd);
+ cd, &my_old_fn, &my_old_cd);
}
store_old(obj, my_old_fn, (struct closure *)my_old_cd, ofn, ocd);
}
STATIC size_t GC_get_maps_len(void)
{
int f = open("/proc/self/maps", O_RDONLY);
- size_t result = GC_get_file_len(f);
+ size_t result;
+ if (f < 0) return 0; /* treat missing file as empty */
+ result = GC_get_file_len(f);
close(f);
return result;
}
/* This only matters with threads enabled, and if we use */
/* this to locate roots (not the default). */
- /* Determine the initial size of /proc/self/maps. */
- /* Note that lseek doesn't work, at least as of 2.6.15. */
# ifdef THREADS
+ /* Determine the initial size of /proc/self/maps. */
+ /* Note that lseek doesn't work, at least as of 2.6.15. */
maps_size = GC_get_maps_len();
if (0 == maps_size) return 0;
# else
word my_mark_no = 0;
IF_CANCEL(int cancel_state;)
+ if ((word)id == (word)-1) return 0; /* to make compiler happy */
DISABLE_CANCEL(cancel_state);
/* Mark threads are not cancellable; they */
/* should be invisible to client. */
marker_mach_threads[(word)id] = mach_thread_self();
# endif
- if ((word)id == (word)-1) return 0; /* to make compiler happy */
-
for (;; ++my_mark_no) {
/* GC_mark_no is passed only to allow GC_help_marker to terminate */
/* promptly. This is important if it were called from the signal */
/* Add the initial thread, so we can stop it. */
{
GC_thread t = GC_new_thread(pthread_self());
+ if (t == NULL)
+ ABORT("Failed to allocate memory for the initial thread.");
# ifdef GC_DARWIN_THREADS
t -> stop_info.mach_thread = mach_thread_self();
# else