Stephen, thanks for the encouragement.
"Stephen J. Turnbull" <stephen(a)xemacs.org> writes:
>>>>> "vin" == Vin Shelton
<acs(a)xemacs.org> writes:
vin> Using dmalloc and repeatedly calling dmalloc_verify(0) in
vin> gdb, I was able to isolate the failure somewhat. The specpdl
vin> gets overwritten in the function execute_optimized_program()
vin> on the 4th time through this code:
Oh, bravo! Good work!
vin> line 480:
------------------------------------------------------------------------
if (!OPAQUEP (f->instructions))
/* Lazily munge the instructions into a more efficient form */
optimize_compiled_function (fun);
/* optimize_compiled_function() guaranteed that f->specpdl_depth is
the required space on the specbinding stack for binding the args
and local variables of fun. So just reserve it once. */
SPECPDL_RESERVE (f->specpdl_depth);
------------------------------------------------------------------------
vin> 1. In this case, optimize_compiled_function() is not
vin> called, so does anything guarantee that "f->specpdl_depth is
vin> the required space on the specbinding stack for binding the
vin> args and local variables of fun"?
Yes, in the sense that the only way that f->instructions should be
OPAQUEP is if o_c_f was called earlier on the byte code. Otherwise it
should be STRINGP (ie, bytecode). Now I'm out of knowledge.
Do you know what function is currently being compiled? It's probably
somewhere in the stack trace (using debug_print from .gdbinit), but I
don't know if that really matters.
(Aside - the only gdbinit file in the current CVS sources lives in my
21.1 source tree:
: ~/cvsroot Mon 17 20:30; find xemacs* -type f | grep gdb
xemacs-21.1/src/gdbinit
xemacs-packages/xemacs-packages/debug/gdbsrc.el
xemacs-packages/xemacs-packages/debug/gdb.el
xemacs-packages/xemacs-packages/debug/gdb-highlight.el
Why doesn't gdbinit appear in 21.4 or 21.5?)
Also, you should be able to debug_print the forms referenced in frames
#14 and #15 to figure out what Lisp is being executed.
OK, here's what I find:
At the top of execute_optimized_program(), I do the following:
(gdb) frame 5
#5 0x0809f50e in funcall_lambda (fun=137970220, nargs=1, args=0xbfffc79c) at eval.c:3863
3863 return unbind_to (speccount, Fprogn (body));
(gdb) ldp fun
Lisp => (lambda (&rest body) (list (quote quote) (byte-compile-eval (cons (quote
progn) body))))
(gdb) lbt
# bind (form)
byte-compile-eval((progn (let (...) (require ...))))
(list (quote quote) (byte-compile-eval (cons ... body)))
# bind (body)
(lambda (&rest body) (list (quote quote) (byte-compile-eval ...)))((let ((load-path
...)) (require (quote cc-bytecomp))))
(eval-when-compile (let (...) (require ...)))
# bind (current-load-list)
# (unwind-protect ...)
# bind (load-file-name)
# (unwind-protect ...)
# (unwind-protect ...)
# (unwind-protect ...)
# (unwind-protect ...)
# (unwind-protect ...)
load-internal("cc-defs.el" nil t t nil nil)
# bind (nosuffix nomessage noerror file)
load("cc-defs.el" nil t t)
# bind (cc-bytecomp-load-depth load-path cc-file cc-part)
cc-bytecomp-load("cc-defs")
(progn (cc-bytecomp-load (symbol-name ...)))
eval((progn (cc-bytecomp-load (symbol-name ...))))
(progn (eval (quote ...)))
eval((progn (eval (quote ...))))
# bind (sym def G16979)
# (unwind-protect ...)
# bind (save-macro-environment form)
byte-compile-eval((progn (eval (quote ...))))
(list (quote quote) (byte-compile-eval (cons ... body)))
# bind (body)
(lambda (&rest body) (list (quote quote) (byte-compile-eval ...)))((eval (quote
(progn ...))))
#<subr macroexpand-internal>((cc-eval-when-compile (cc-bytecomp-load (symbol-name
...))) ((byte-compiler-options lambda (&rest forms) (apply ... forms))
(eval-when-compile lambda (&rest body) (list ... ...)) (eval-and-compile lambda
(&rest body) (byte-compile-eval ...) (cons ... body))))
# bind (cl-macro-environment cl-env cl-macro)
macroexpand((cc-eval-when-compile (cc-bytecomp-load (symbol-name ...)))
((byte-compiler-options lambda (&rest forms) (apply ... forms)) (eval-when-compile
lambda (&rest body) (list ... ...)) (eval-and-compile lambda (&rest body)
(byte-compile-eval ...) (cons ... body))))
# bind (byte-compile-current-form handler form)
byte-compile-file-form((cc-eval-when-compile (cc-bytecomp-load (symbol-name ...))))
mapcar(byte-compile-file-form ((cc-eval-when-compile (cc-bytecomp-load ...)) (require
(quote cc-defs))))
# bind (form)
byte-compile-file-form-progn((progn (cc-eval-when-compile (cc-bytecomp-load ...))
(require (quote cc-defs))))
# bind (byte-compile-current-form handler form)
byte-compile-file-form((progn (cc-eval-when-compile (cc-bytecomp-load ...)) (require
(quote cc-defs))))
# bind (byte-compile-current-form handler form)
byte-compile-file-form((cc-require (quote cc-defs)))
# (unwind-protect ...)
#<compiled-function nil "...(43)" [byte-compile-unresolved-functions
byte-compile-inbuffer 1 " \n
" nil looking-at ";" byte-compile-file-form read
byte-compile-flush-pending byte-compile-warn-about-unresolved-functions] 3>()
# (unwind-protect ...)
call-with-condition-handler(#<compiled-function (error-info) "...(4)"
[error-info byte-compile-report-error] 2> #<compiled-function nil
"...(43)" [byte-compile-unresolved-functions byte-compile-inbuffer 1 " \n
" nil looking-at ";" byte-compile-file-form read
byte-compile-flush-pending byte-compile-warn-about-unresolved-functions] 3>)
# (unwind-protect ...)
# bind (byte-compile-warnings-beginning byte-compile-point-max-prev
byte-compile-log-buffer byte-compile-macro-environment byte-compile-function-environment
byte-compile-autoload-environment byte-compile-unresolved-functions
byte-compile-bound-variables byte-compile-free-references byte-compile-free-assignments
byte-compile-verbose byte-optimize byte-compile-emacs19-compatibility byte-compile-dynamic
byte-compile-dynamic-docstrings byte-compile-warnings byte-compile-file-domain
byte-compile-outbuffer float-output-format case-fold-search print-length print-level
byte-compile-constants byte-compile-variables byte-compile-tag-number byte-compile-depth
byte-compile-maxdepth byte-compile-output eval filename byte-compile-inbuffer)
byte-compile-from-buffer(#<buffer " *Compiler Input*">
"/opt/build/xemacs-packages-2003-02-15/xemacs-packages/cc-mode/cc-align.el")
# bind (byte-compile-current-file target-file input-buffer output-buffer
byte-compile-dest-file load filename)
byte-compile-file("cc-align.el")
byte-code("..." [file byte-compile-file t] 2)
# (condition-case ... . ((error (byte-code "ÂÃ!!ÂÄ!ÅÆ!«Æ Ç\"ªÂ @ÈN®
@!ÉÊ A\"ÂË!Ç" ... 3))
# bind (file)
batch-byte-compile-1("cc-align.el")
# bind (error file-to-process)
batch-byte-compile-one-file()
# bind (error)
batch-byte-compile()
# bind (arg)
command-line-do-funcall("-f")
# bind (dir file-count line end-of-options file-p arg tem)
command-line-1()
# bind (command-line-args-left)
command-line()
# (condition-case ... . ((t (byte-code " oÂ" ... 1))))
# bind (error-data)
normal-top-level()
# (condition-case ... . error)
# (catch top-level ...)
Now bearing that lisp backtrace in mind, I found out another
interesting bit of info - if I don't byte-compile cc-bytecomp.el
before attempting to byte-compile cc-align.el, then I can byte-compile
cc-align.el without any difficulty. In fact, this patch:
--- xemacs-packages/cc-mode/Makefile~ 2003-01-13 16:03:00.000000000 -0500
+++ xemacs-packages/cc-mode/Makefile 2003-02-17 21:33:51.000000000 -0500
@@ -25,9 +25,9 @@
REQUIRES = xemacs-base mail-lib
CATEGORY = standard
-ELCS = cc-bytecomp.elc cc-align.elc cc-cmds.elc cc-compat.elc cc-defs.elc \
+ELCS = cc-align.elc cc-cmds.elc cc-compat.elc cc-defs.elc \
cc-engine.elc cc-guess.elc cc-langs.elc cc-lobotomy.elc cc-make.elc \
- cc-menus.elc cc-mode-19.elc cc-mode.elc cc-styles.elc cc-vars.elc
+ cc-menus.elc cc-mode-19.elc cc-mode.elc cc-styles.elc cc-vars.elc cc-bytecomp.elc
INFO_FILES = $(PACKAGE).info*
HTML_FILES = $(PACKAGE)*.html
(i.e. moving cc-bytecomp to the end of the elc list) enables me to
successfully build the bindist target in cc-mode.
Is it possible that the byte compiler is screwing up the definition of
cc-eval-when-compile?
This is quite fun and educational, but I'd be happy to receive further
enlightenment from anyone interested.
Thanks,
Vin
PS. All of the reported experiments include Ben's patch:
http://list-archive.xemacs.org/xemacs-patches/200302/msg00083.html.
Although I will see the coredump without that patch, my precise recipe
requires that patch to be applied. Without it, the memory overwrite
occurs in a different (as yet undetermined) place.