Hello- I have a reproducible SEGV during GC of SMOBs on Guile 2.0.7. It was also present in 2.0.6.
To reproduce compile main.c as $ gcc -std=gnu99 -shared -o smobbug.so -Wall -Wextra `pkg-config guile-2.0 --cflags --libs` -fPIC main.c Then with $ LD_PRELOAD=./smobbug.so LD_LIBRARY_PATH=. GUILE_LOAD_PATH=. guile ;; At the repl, load the lib (use-modules (smobbug)) ;; Make a SMOB to be GC'd (handlesmob-init) ;; Trigger a GC from the GC thread (string-length (make-string 10000000)) This gives Program received signal SIGSEGV, Segmentation fault. [Switching to Thread 0xb7d98b40 (LWP 20488)] 0xb7f251ab in smob_mark (addr=0x8608ff0, mark_stack_ptr=0xb7d90308, mark_stack_limit=0xb7d982f0, env=0) at smob.c:325 325 SCM_I_CURRENT_THREAD->current_mark_stack_ptr = mark_stack_ptr; Here's what's happening internally. When Guile starts up, it creates 3 threads * Initial thread * GC thread from scm_storage_prehistory GC_INIT() * signal delivery thread That second thread is the one from which automatic garbage collection occurs. The way that thread gets created, it has an scm_i_current_thread == NULL, apparently. So dereferencing scm_i_current_thread causes null dereference. And smob_mark() will dereference scm_i_current_thread when collecting a smob with a mark function. -Mike
(define-module (smobbug) #:export ( handlesmob-init )) (load-extension "smobbug" "smobbug_init") (define (handlesmob-init) "docstring" (%handlesmob-init))
#define _GNU_SOURCE #include <stdio.h> #include <libguile.h> static scm_t_bits handlesmob_tag; void smobbug_init (void); SCM mark_handle (SCM x); SCM handlesmob_init () { SCM s_handlesmob; char *handle; handle = malloc (1); return SCM_NEWSMOB (s_handlesmob, handlesmob_tag, handle); } SCM mark_handlesmob (SCM x) { // No SCMs in the handle type: nothing to do here. return (SCM_BOOL_F); } size_t free_handlesmob (SCM handle) { SCM_ASSERT (SCM_SMOB_PREDICATE (handlesmob_tag, handle), handle, SCM_ARG1, "free-handlesmob"); char *m = SCM_SMOB_DATA (handle); if (m != NULL) free (m); return 0; } int print_handlesmob (SCM x, SCM port, scm_print_state *pstate) { char *frm = (char *) SCM_SMOB_DATA (x); char *str; scm_puts ("#<handlesmob ", port); if (frm == (char *) NULL) { scm_puts ("(freed)", port); } else { if (asprintf (&str, "%p", frm) < 0) scm_puts ("???", port); else scm_puts (str, port); } scm_puts (">", port); // non-zero means success return 1; } void smobbug_init () { handlesmob_tag = scm_make_smob_type ("handlesmob", sizeof (char *)); scm_set_smob_mark (handlesmob_tag, mark_handlesmob); scm_set_smob_free (handlesmob_tag, free_handlesmob); scm_set_smob_print (handlesmob_tag, print_handlesmob); scm_c_define_gsubr ("%handlesmob-init", 0, 0, 0, handlesmob_init); }