emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RE: address@hidden: RE: weird defadvice bug withbyte-compilation]


From: Drew Adams
Subject: RE: address@hidden: RE: weird defadvice bug withbyte-compilation]
Date: Fri, 9 Dec 2005 10:37:16 -0800

    I'm not sure it was fixed.  Chong Yidong didn't say what he saw on
    GNU/Linux when he tried this, but on MS-Windows, with today's CVS, I
    see the following (after replacing "C:\\drews-lisp-20" with the
    directory where I put foo.el and bar.el --- Chong, did you do that on
    GNU/Linux?):

      . Typing "C-x C-e" to evaluate `(require 'foo)' throws an error:

        Debugger entered--Lisp error: (void-variable my-mode)...

      .  Typing "C-x C-c" at this point, i.e., after the above traceback
         was shown, does pop up the Emacs Abort Dialog.

Thanks fo looking into this problem on Windows. What Eli reports is exactly
what I saw and see.

    The Lisp error is thrown for a good reason, AFAICT: `my-mode' was
    never defined.  Drew, should it be?

Yes and no. Yes, for my program to work; no, to reproduce the bug. If it is
defined explicitly, then the error does not occur. (The error to be
concerned about here is obviously the fatal error that results, not the
error of the variable not being bound.)

Here is some background on the variable binding, however - the real context:

1. In file foo.el, I do the defadvice before I do a define-minor-mode that
defines (and binds) the variable my-mode. If I move the defadvice in foo.el
after the define-minor-mode, there is no problem. ("So", the doctor said,
"if it hurts, just don't do that".)

However, I'm not clear on why I should need to do that. Does the defadvice
really need my-mode to be bound? I thought that defadvice's last arg (BODY),
in this case just my-mode, was treated by defadvice as unevaluated code, to
be evaluated only when the advised function is called. In the case in
question, the function next-history-element is never called, so I don't
understand why my-mode is evaluated.

It is apparently evaluated by x-create-frame, but I don't see why. Looking
further up the debug stack, there is an automatic byte-compilation of the
advised next-history-element. It's not clear to me if the variable is
evaluated at that point or just by x-create-frame. I don't see why
x-create-frame would evaluate the variable, and I don't see why the variable
would be evaluated during byte-compilation.

2. Secondly, I'm not real clear on the use of define-minor-mode, I guess.
This library works with both Emacs 20 and 22. For Emacs 20, I do an explicit
defcustom to define my-mode, and I do that before defining the minor-mode
function my-mode - no problem. For Emacs 22, I do the define-minor-mode at
the same place I do the Emacs 20 defun my-mode.

I was expecting that define-minor-mode would DTRT: it would somehow define
the variable early enough - but I guess that's not possible. I will move the
define-minor-mode forward, but it makes the library a bit less readable. I
like to put all defcustoms and defvars at the beginning (after macro
definitions), before any function definitions. I think of define-minor-mode
as essentially a function definition, but it is in fact also a variable
definition, so I guess I need to move it forward.

You'll say that defadvice also (re)defines a function, and the only need
here is to move the define-minor-mode before the defadvice. That's true.
There was a certain logic to the order of the function definitions, but
that's less important now than making things work! I'll move the
define-minor-mode forward, and say no more.

That changes nothing about the bug, of course - Emacs should not end in a
fatal error just because a variable is not bound. And I still have the
question about why the unbound variable was evaluated (during advice
compilation? during frame creation?).

--

Oops - last minute addition. It just occurred to me that the unbound
variable is being evaluated by x-create-frame in order to set the minor-mode
mode-line indication. (Should users need to be concerned about binding that
variable, even though they have used define-minor-mode?) I think, then, that
there may be a second bug here, besides ungracefully treating an unbound
variable.

Again, however, there seem to be several things interacting here, because I
found that if I remove any part of the code I submitted with the bug, the
bug goes away. This suggests that it involves: 1) the mode-line indication
(minor-mode-map-alist), 2) the menu-enable condition (that's the code that
provokes the error message by evaluating the unbound variable), 3) the
keymap, 4) the defadvice in foo.el, and 5) the defadvice in bar.el.

Clarification welcome.

Thanks,

  Drew

    If I run Emacs from GDB, I get the following backtrace after I click
    YES in the abort dialog:

        (gdb) bt 20
        #0  0x7c901231 in ntdll!DbgUiConnectToDbg () from ntdll.dll
        #1  0x011319c7 in w32_abort () at w32fns.c:8949
        #2  0x01084cee in check_glyph_memory () at dispnew.c:2583
        #3  0x010018c3 in shut_down_emacs (sig=0, no_x=0, stuff=23861249)
        at emacs.c:2167
        #4  0x01001929 in Fkill_emacs (arg=23861249) at emacs.c:2072
        #5  0x0100c5da in Ffuncall (nargs=1, args=0x82c1b0) at eval.c:2879
        #6  0x011094f9 in Fbyte_code (bytestr=18486379,
    vector=18486500, maxdepth=40)
        at bytecode.c:694
        #7  0x0100bfae in funcall_lambda (fun=18486332, nargs=1,
    arg_vector=0x82c374)
        at eval.c:3066
        #8  0x0100c3a1 in Ffuncall (nargs=2, args=0x82c370) at eval.c:2934
        #9  0x01107858 in Fcall_interactively (function=24463457,
        record_flag=23861249, keys=23920644) at callint.c:884
        #10 0x0104ca3e in Fcommand_execute (cmd=24463457,
    record_flag=23861249,
        keys=23861249, special=23861249) at keyboard.c:9734
        #11 0x01053279 in command_loop_1 () at keyboard.c:1777
        #12 0x0100a81b in internal_condition_case (bfun=0x1052f39
    <command_loop_1>,
        handlers=23925361, hfun=0x104d397 <cmd_error>) at eval.c:1465
        #13 0x010479b7 in command_loop_2 () at keyboard.c:1315
        #14 0x0100a750 in internal_catch (tag=23949793,
        func=0x1047994 <command_loop_2>, arg=23861249) at eval.c:1211
        #15 0x0104777f in command_loop () at keyboard.c:1282
        #16 0x01047867 in recursive_edit_1 () at keyboard.c:987
        #17 0x0104797d in Frecursive_edit () at keyboard.c:1048
        #18 0x0100c5e5 in Ffuncall (nargs=1, args=0x82c880) at eval.c:2876
        #19 0x011094f9 in Fbyte_code (bytestr=32152067,
    vector=27025668, maxdepth=32)
        at bytecode.c:694
        (More stack frames follow...)

        Lisp Backtrace:
        "kill-emacs"
        "save-buffers-kill-emacs"
        "call-interactively"
        "recursive-edit"
        "byte-code"
        "debug"
        "and"
        "x-create-frame"
        "x-create-frame-with-faces"
        "make-frame"
        "special-display-popup-frame"
        "display-buffer"
        "display-warning"
        "byte-compile-log-warning"
        "byte-compile-warn"

    I will try to debug this when I have time (any ideas are welcome), but
    in the meantime, I see already that the problem that causes Emacs to
    commit suicide in frame #2 is that glyph_matrix_count is 8 instead of
    0.  Here's the code of check_glyph_memory:

        /* Check glyph memory leaks.  This function is called from
           shut_down_emacs.  Note that frames are not destroyed when Emacs
           exits.  We therefore free all glyph memory for all active frames
           explicitly and check that nothing is left allocated.  */

        void
        check_glyph_memory ()
        {
          Lisp_Object tail, frame;

          /* Free glyph memory for all frames.  */
          FOR_EACH_FRAME (tail, frame)
        free_glyphs (XFRAME (frame));

          /* Check that nothing is left allocated.  */
          if (glyph_matrix_count)
        abort ();
          if (glyph_pool_count)
        abort ();
        }

    It sounds like some frame's glyph matrices were not freed for some
    reason?






reply via email to

[Prev in Thread] Current Thread [Next in Thread]