tags 516328 + patch
thanks
Hi,
It turns out the problem has nothing to do with the pipe or fork
procedures. It occurs whenever enough consing happens to trigger a GC
(but not from the toplevel of the .xbindkeysrc.scm file--see below).
A third test case is attached which demonstrates this, test-3.scm.
The Guile GC was trying to free a string object that was backed by
static memory. The string in question named the xbindkeys
initialization file. The Guile string object was constructed with the
scm_take0str C function in options.c:857(get_rc_guile_file). This
function expects dynamically-allocated memory, and it takes
responsibility to free it with a future GC. However, the string given
to scm_take0str ("rc_guile_file") is statically-allocated
(xbindkeys.c:55).
The fix is simple: use scm_makfrom0str, which copies its given C
string to newly-allocated memory which is then associated with the
Guile string it returns, making the returned string safe to GC. All
three test cases pass, on i386 and amd64, with this fix:
--- orig/xbindkeys-1.8.2/options.c 2007-04-18 14:47:03.000000000 -0700
+++ xbindkeys-1.8.2/options.c 2009-02-21 08:38:25.000000000 -0800
@@ -854,7 +854,7 @@
fclose (stream);
init_xbk_guile_fns();
- scm_primitive_load(scm_take0str(rc_guile_file));
+ scm_primitive_load(scm_makfrom0str(rc_guile_file));
return 0;
}
I'm guessing that the reason the problem doesn't occur on the toplevel
is because scm_primitive_load is still on the stack, holding a
reference to the Guile source file name string it was given. The only
thing "magical" about the xbindkey-function procedure is that the
procedure that is passed to it is eventually called asynchronously,
after scm_primitive_load has finished, and the Guile string naming the
source file is unreachable.
I guess nobody else does anything interesting enough with their Scheme
code in .xbindkeysrc.scm to trigger a GC. :)
--
J.P. Larocque: <[email protected]>, +1 509 324-2410
(define (cons-a-bit)
(define (zero-to-99)
(let loop ((i 0)
(acc '()))
(if (= i 100)
(reverse acc)
(loop (+ 1 i) (cons* i acc)))))
(display (number->string (car (last-pair (zero-to-99)))))
(newline))
(define (cons-loop)
(let loop ()
(cons-a-bit)
(loop)))
(xbindkey-function '("F10") cons-loop)
;;; The problem cannot be reproduced directly here, on the toplevel of
;;; the rc file: (uncomment and try xbindkeys with -n from a terminal)
;(cons-loop)