[Top][All Lists]

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

bug#7728: 24.0.50; GDB backtrace from abort

From: Drew Adams
Subject: bug#7728: 24.0.50; GDB backtrace from abort
Date: Thu, 13 Jan 2011 22:46:15 -0800

> > > > In this case the `save-window-excursion' should amount to a 
> > > > no-op in the end. The source and target window and frame need
> > > > not be the same in general, but they are the same in the
> > > > crashes I reported.
> > > 
> > > I don't believe this to be true, at least not from 
> > > Emacs's internals POV.  The code that crashes clearly
> > > executes the branch where the frame recorded by
> > > save-window-excursion is NOT the selected frame by
> > > the time the body of save-window-excursion is done being 
> > > evaluated.
> > 
> > As I said, I followed the _source_ code in the debugger.  
> > And the source code does not cause a crash.  The source code
> > lets us know what _should_ be happening here, not what is
> > actually happening that provokes a crash.
> Since you couldn't reproduce the crash under the Lisp debugger, the
> evidence you collected during that debugging session is not really
> admissible in the court of Emacs bugs ;-)

I did not _try_ to reproduce the crash under the Lisp debugger.  [But see very
end of this message.]

I'm not trying or being tried in a court case.  I tried ;-) only to find the
context (windows, frame) of the correct behavior in this case, to let you know
which window should have been selected etc.  I had already sent you the info
about which window was _actually_ selected in the crash - as you requested (`p
selected_window' etc.).

> IOW, the backtrace you posted clearly shows that somehow,
> save-window-excursion needed to switch frames, and its code that
> restores the original window configuration therefore needed to select
> a different frame.  That is a fact revealed by the C backtrace.  If we
> want to make sure that this frame switch is real, I would suggest to
> look at the values of sf and w->frame in this fragment from
> select-window:
>   sf = SELECTED_FRAME ();
>   if (XFRAME (WINDOW_FRAME (w)) != sf)
>     {
>       XFRAME (WINDOW_FRAME (w))->selected_window = window;
>       /* Use this rather than Fhandle_switch_frame
>        so that FRAME_FOCUS_FRAME is moved appropriately as we
>        move around in the state where a minibuffer in a separate
>        frame is active.  */
>       Fselect_frame (WINDOW_FRAME (w), norecord);
> For that, you need to reproduce the crash, then go to the call-stack
> frame where select-window (Fselect_window) invokes select-frame
> (Fselect_frame).  In your original backtrace, this was frame #15:
>  #12 0x01288ef3 in Fredirect_frame_focus (frame=93005829, 
> focus_frame=93005829)
>      at frame.c:2082
>  #13 0x0127f4c8 in do_switch_frame (frame=93005829, track=1, 
> for_deletion=0,
>      norecord=49010714) at frame.c:847
>  #14 0x01280733 in Fselect_frame (frame=93005829, 
> norecord=49010714) at
>  frame.c:899
>  #15 0x01252702 in Fselect_window (window=93006853, 
> norecord=49010714) at
>  window.c:3581
>  #16 0x0125e7c8 in Fset_window_configuration 
> (configuration=99327941) at
>  window.c:6148
> So in that case, you would need to issue the following GDB commands:
>  (gdb) frame 15
>  (gdb) p sf->name
>  (gdb) xstring
>  (gdb) p w->frame
>  (gdb) xframe

Here you are:

$ ./gdb -p 448
GNU gdb (GDB) 7.2
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "mingw32".
For bug reporting instructions, please see:
Attaching to process 448
[New Thread 448.0xde8]
[New Thread 448.0x784]
[New Thread 448.0x650]
[New Thread 448.0x1f8]
Reading symbols from C:\Emacs-24-2011-01-03\bin\emacs.exe...done.
[Switching to Thread 448.0x1f8]
Warning: c:\drews-lisp-20\bin/../lwlib: No such file or directory.
SIGINT is used by the debugger.
Are you sure you want to change it? (y or n) [answered Y; input not from
Environment variable "DISPLAY" not defined.
TERM = cygwin
Breakpoint 1 at 0x1308a1c: file w32fns.c, line 7298.
Temporary breakpoint 2 at 0x11cf0c9: file sysdep.c, line 839.
(gdb) c

Program received signal SIGTRAP, Trace/breakpoint trap.
[Switching to Thread 448.0xde8]
0x7c90120f in ntdll!DbgUiConnectToDbg () from C:\WINDOWS\system32\ntdll.dll
(gdb) bt
#0  0x7c90120f in ntdll!DbgUiConnectToDbg () from C:\WINDOWS\system32\ntdll.dll
#1  0x01308a53 in w32_abort () at w32fns.c:7312
#2  0x01049f03 in die (msg=0x1592fbc "assertion failed:
    file=0x1592e80 "xdisp.c", line=1156) at alloc.c:6129
#3  0x01162d06 in window_text_bottom_y (w=0x3beba00) at xdisp.c:1156
#4  0x011c0737 in erase_phys_cursor (w=0x3beba00) at xdisp.c:23805
#5  0x011c19fb in display_and_set_cursor (w=0x3beba00, on=1, hpos=2, vpos=6,
x=16, y=87)
    at xdisp.c:23939
#6  0x011c1b14 in update_window_cursor (w=0x3beba00, on=1) at xdisp.c:23976
#7  0x011c1cce in update_cursor_in_window_tree (w=0x3beba00, on_p=1) at
#8  0x011c1e18 in x_update_cursor (f=0x31aee00, on_p=1) at xdisp.c:24010
#9  0x012ea74b in frame_unhighlight (f=0x31aee00) at w32term.c:2750
#10 0x012eac1a in x_frame_rehighlight (dpyinfo=0x16c5928) at w32term.c:2899
#11 0x012eaa66 in w32_frame_rehighlight (frame=0x31aee00) at w32term.c:2873
#12 0x01288a2b in Fredirect_frame_focus (frame=52096517, focus_frame=58733573)
    at frame.c:2082
#13 0x0127f000 in do_switch_frame (frame=58733573, track=1, for_deletion=0,
    norecord=49006618) at frame.c:847
#14 0x0128026b in Fselect_frame (frame=58733573, norecord=49006618) at
#15 0x01252132 in Fselect_window (window=59380741, norecord=49006618) at
#16 0x0125e2f5 in Fset_window_configuration (configuration=84414149) at
#17 0x0103c8aa in unbind_to (count=42, value=64910257) at eval.c:3325
#18 0x010d3ffa in read_minibuf (map=48995734, initial=66396897, prompt=55090145,
    backup_n=20, expflag=0, histvar=49192130, histpos=0, defalt=66396897,
    allow_props=1, inherit_input_method=0) at minibuf.c:805
#19 0x010d4807 in Fread_from_minibuffer (prompt=55090145,
    keymap=48995734, sys_read=49006618, hist=49192130, default_value=66396897,
    inherit_input_method=49006618) at minibuf.c:998
#20 0x0103b09e in Ffuncall (nargs=8, args=0x83e920) at eval.c:2969
#21 0x010f32b0 in Fbyte_code (bytestr=59961409, vector=55568133, maxdepth=32)
    at bytecode.c:679
#22 0x0103bae2 in funcall_lambda (fun=50305061, nargs=7, arg_vector=0x83ebe4)
    at eval.c:3129
#23 0x0103b1f9 in Ffuncall (nargs=8, args=0x83ebe0) at eval.c:2992
#24 0x010f32b0 in Fbyte_code (bytestr=60324673, vector=60286981, maxdepth=32)
    at bytecode.c:679
#25 0x0103bae2 in funcall_lambda (fun=52589221, nargs=8, arg_vector=0x83eea4)
    at eval.c:3129
#26 0x0103b1f9 in Ffuncall (nargs=9, args=0x83eea0) at eval.c:2992
#27 0x010f32b0 in Fbyte_code (bytestr=60321889, vector=55379013, maxdepth=36)
    at bytecode.c:679
#28 0x01038de5 in Feval (form=59632374) at eval.c:2358
#29 0x01036494 in internal_catch (tag=60939554, func=0x10382ac <Feval>,
    at eval.c:1206
#30 0x010f3ead in Fbyte_code (bytestr=60322641, vector=55367685, maxdepth=40)
    at bytecode.c:854
#31 0x0103bae2 in funcall_lambda (fun=52589573, nargs=7, arg_vector=0x83f440)
    at eval.c:3129
#32 0x0103b508 in apply_lambda (fun=52589573, args=58014910, eval_flag=1) at
#33 0x01039269 in Feval (form=58014966) at eval.c:2397
#34 0x01034591 in Fsetq (args=58015062) at eval.c:496
#35 0x010387e8 in Feval (form=58015070) at eval.c:2299
#36 0x01034415 in Fprogn (args=57946062) at eval.c:397
#37 0x01035fd9 in Flet (args=58015078) at eval.c:1054
#38 0x010387e8 in Feval (form=58015214) at eval.c:2299
#39 0x010f69da in Fcall_interactively (function=49554322, record_flag=49006618,
    keys=49027845) at callint.c:345
#40 0x0103adae in Ffuncall (nargs=4, args=0x83fb60) at eval.c:2950
#41 0x0103a228 in call3 (fn=49175466, arg1=49554322, arg2=49006618,
    at eval.c:2775
#42 0x010227ad in Fcommand_execute (cmd=49554322, record_flag=49006618,
    special=49006618) at keyboard.c:10393
#43 0x01006bcd in command_loop_1 () at keyboard.c:1726
#44 0x01036a15 in internal_condition_case (bfun=0x100562b <command_loop_1>,
    handlers=49060250, hfun=0x1004d5f <cmd_error>) at eval.c:1462
#45 0x01005231 in command_loop_2 (ignore=49006618) at keyboard.c:1327
#46 0x01036494 in internal_catch (tag=49058346, func=0x100520d <command_loop_2>,
    arg=49006618) at eval.c:1206
#47 0x010051ed in command_loop () at keyboard.c:1306
#48 0x0100446b in recursive_edit_1 () at keyboard.c:929
#49 0x01004985 in Frecursive_edit () at keyboard.c:991
#50 0x010027d7 in main (argc=3, argv=0x33c58) at emacs.c:1716

Lisp Backtrace:
"old-read-from-minibuffer" (0x83e924)
"read-from-minibuffer" (0x83ebe4)
"icicle-lisp-vanilla-completing-read" (0x83eea4)
"byte-code" (0x83f0c4)
"completing-read" (0x83f440)
"setq" (0x83f69c)
"let" (0x83f85c)
"call-interactively" (0x83fb64)
(gdb) frame 15
#15 0x01252132 in Fselect_window (window=59380741, norecord=49006618) at
3586    window.c: No such file or directory.
        in window.c
(gdb) p sf->name
$1 = 63915633
(gdb) xstring
$2 = (struct Lisp_String *) 0x3cf4670
(gdb) p w->frame
$3 = 58733573
(gdb) xframe
$4 = (struct frame *) 0x3803400
"Emacs minibuffer", ' ' <repeats 25 times>, "show/hide: hold CTRL + click in

> The 3rd and the 5th command will display the names of the two frames,
> the one that's selected at this point, and the one to which the window
> w (from the configuration being restored) belongs, respectively.  We
> could then try to understand how come Emacs thinks it needs to switch
> frames, while your analysis of the Lisp code suggests these two should
> have specified the same frame.
> (Note that frame #15 could have a different number in a different
> crash, so look for the frame whose description is the same as what is
> shown about, i.e. a call from Fselect_window to Fselect_frame, and use
> the number of that frame.)

FYI - `drews-lisp-20' was a frame with a Dired listing.  It was the selected
frame when I hit `C-h f'.  `Emacs minibuffer ... click in window' is the name of
the standalone minibuffer frame.  The only other frame was the `*Completions*'
frame, which is where I clicked the completion candidate `display-graphic-p'
with `mouse-2' - that click provoked the crash.  The `*Completions*' frame has
its input redirected to the minibuffer frame (which it should).


Let me know if I did what you need or you would like me to do something else.

Note too that when I spoke of the behavior (using the source code) in the
debugger, and I said that the selected window and frame were the same for the
save-window-excursion, I was following the execution of
`1on1-fit-minibuffer-frame' (which calls `fit-frame', where the
`save-window-excursion' occurs that you pointed to).

In the above gdb backtrace, I think we may be looking at something different.
That speaks of the frame that was selected before `C-h f' (`drews-lisp-20'),
i.e. before any call to `1on1-fit-minibuffer-frame', hence before the minibuffer
frame/window would have been selected, if it was at all when running the byte

I mention this just so you make the difference.  The sequence of actions is:

selected frame is `d-l-20'

I hit `C-h f'

minibuffer becomes active

I type `g r a p h i c' and hit `S-TAB' to complete (and open frame

I click `mouse-2' on candidate `display-graphic-p' in `*Completions*'


Where does `1on1-fit-minibuffer-frame' come in?  It is on `post-command-hook',
so it is run when the minibuffer is exited.  It is that that calls `fit-frame'
to (re-)fit the minibuffer frame by calling `fit-frame'.  It is you who pointed
to `fit-frame' and its `save-window-excursion', as being the likely place where
the problem arises.


> > > > * Let me repeat that the _source code works fine_ - no 
> > > > error, no crash, no bug.
> > > > 
> > > > * Let me repeat too that the byte-compiled code (no matter 
> > > > which Emacs version it was compiled with) works fine in all
> > > > Emacs versions except the current development code - no error,
> > > > no crash, no bug.
> > > 
> > > I don't think this to be relevant, sorry.
> > 
> > Why?  The only thing new to the mix is the new Emacs dev 
> > version.  The source code and the byte-compiled code are the
> > same as before.  The regression is not realized using the
> > source code.  It happens only with the new dev version when
> > it executes the byte code.  Why isn't that relevant?
> Because we have the C backtrace (thanks to you).  And that backtrace
> speaks for itself.  There's nothing in it that cannot be understood
> without invoking some non-trivial bug in the compiled byte code.  So,
> while it's certainly possible that byte compilation has some unwanted
> effect here, it sounds extremely unlikely, certainly not the first
> explanation we should try.
> > > I'm inclined to think that it's some weird side effect of
> > > Edebug, or maybe something else.
> > 
> > You think _what_ is a weird effect of edebug?
> The fact that uncompiled code seems to avoid the crash.

The uncompiled code avoids the crash both with and without the debugger.  No
weird effect of edebug (or `debug') could possibly be the reason that the
uncompiled code avoids the crash when the debugger is not even used.

> > With the debugger there was no crash.  So it certainly cannot be
> > some weird effect of the debugger that is causing the crash.
> The way I see it, you had a crash with byte-compiled code without the
> debugger, and you had no crash with uncompiled code under the
> debugger.  Which of these two variables caused the difference in
> behavior remains to be seen.

I also have no crash (ever) with uncompiled code without the debugger.
Uncompiled code has no crash with or without the debugger.  So I don't see why
you are still asking yourself questions about variables.  The crash is
reproducible only with the byte-compiled code.  I did not try to reproduce the
crash with byte-compiled code while using the debugger.  I can do that if you
like.  I didn't do that because the debugger shows less info with byte-compiled
code and I was trying to find the windows etc. that should have been involved
(when there is no crash).

> > > > This is a _regression_ due to some change in the development
> > > > version that no longer plays well with the byte-compiled code.
> > > 
> > > That's a possibility, but I think it's a remote one.
> > 
> > Seems more like an inescapable conclusion, to me.  
> > Substitute any other Emcs version and presto: no problem.
> > Substitute the source code for the byte code and presto: no problem.
> To really convince me in this, you would have to run Emacs under GDB,
> using the source Lisp code, step through all the functions involved in
> the crash, and show that the crash is indeed avoided, and why.
> If you give me a reproducible recipe for the crash, I might try doing
> this myself.

The latest recipe I've been using uses all of my setup.  I have not tried to
pare things down.

But IIRC I gave you a minimal recipe the first time around, at the beginning of
this thread (or perhaps in mails between us before the thread).  You should be
able to use that recipe.  If you cannot find it and you still need to do this,
let me know and I'll try to find it.

> > > The offending code
> > 
> > What offending code?
> The one that sets to nil the internal variable which holds the
> selected window.  That's what triggers the crash, because way down the
> call-stack, Emacs tries to reference the mode-line face of the frame
> held in that variable.
> > What you see as offending code, if it was already in 21.1, 
> > did not present a problem - it wasn't offending anyone.
> Ever heard of bugs that lurk and rear their ugly head years after they
> were introduced?
> > > has been in Emacs since v21.1, so the problem is not new 
> > > in any way.
> > 
> > Of course the problem is new.  It's a _regression_.
> Only if the issue is looked at phenomenologically.  From my POV, this
> bug was there for years.
> > There is no such crash in any prior Emacs version.
> But you have never before used any Emacs binary compiled with
> ENABLE_CHECKING, did you?  Only such a version will crash, because it
> does extra checking.
> > You and I have different views of what "the problem"
> > is, I guess.  For me, the problem is the crash.  That's new.
> We can never fix the crash unless we understand what code causes it,
> and why.  I posted here many messages ago why it crashes, and what
> I found does not need to invoke any mysterious changes introduced
> by the byte compiler to explain the crash.

I never suggested any changes, mysterious or otherwise, _introduced by the
byte-compiler_.  On the contrary, I've said several times that it does not
matter whether I byte-compile in Emacs 20 or 24.  Any changes in the
byte-compiler since Emacs 20 are irrelevant (unless there are two different
crash causes).

What I said was that the crash occurs only with the byte-compiled code (no
matter how it was compiled - which version) and only when using Emacs 24 (for
the test, not for byte-compiling).  My guess was that it is changes _introduced
in Emacs 24_ which are the problem, not changes in the byte-compiler.

But you are quite right that it might not be _development_ changes introduced in
Emacs 24 but just the simple change to using ENABLE_CHECKING that makes the
difference.  I wasn't aware of that difference.  That's still a difference in
the version, in the sense I was using: it is the Emacs binary that is different,
not the source or byte code.

> It is crystal clear that,
> under specific and well-defined circumstances set-window-configuration
> and any code that calls it, including save-window-excursion, can crash
> in the same way, if the window configuration being restored was
> recorded in a different frame.  _That_ is the problem I'm trying to
> fix in this bug.
> While the crash in your specific use-case could indeed be new (if it
> is explained by something other than the fact you are for the first
> time using a binary compiled with ENABLE_CHECKING), the defect in the
> code that I found and described could cause crashes in any number of
> other use-cases, which have nothing to do with byte-compiling.  I'm
> trying to find a solution for all those use-cases, not just for yours.
> > > I think you interpret the latest messages incorrectly.  No one is
> > > arguing that your code is the culprit.  The correct way 
> > > to fix this bug was pointed out by Stefan several messages ago, and I 
> > > will do just that when I have time.
> > 
> > I did not understand that you have a solution.  I didn't 
> > get that impression from your asking me to check the selected
> > window in the debugger etc.
> I asked that to have more evidence to back up my analysis.  It's never
> a bad idea to look for more evidence, because sometimes it can
> contradict the best hypothesis and change the whole picture.

Let me know if you need something more from me.  I'm hoping that you will not
need me to try to pare down my setup to give you a simple recipe to reproduce.
But if necessary I'll try to find time to do that (but not now).



Below, I tried to trace `1on1-fit-minibuffer-frame' in the debugger using the
byte-compiled version of `fit-frame.el'.  I just copied (or typed again) most of
the text as I hit `d' etc., so this is not just a copy of the debugger buffer.

First, there was no crash.  Second, I have no idea why that Lisp error was
raised at the end.  (I do have `mouse-choose-completion' defaliased, but to a
definition that is very similar to the original and whose interactive spec is
(interactive "e") - an event with params.

Also, if I load the source file that defines it, I am able to choose a
completion using mouse-2 without a crash and without raising the error.  (I've
never seen that error anyway, except this time with byte-compiled code in the

Now I'm thinking that these recent crashes might not be the same as the crash I
wrote about originally (though you said you think they are the same, so at some
level they must be).

I see now that if, starting with only byte-compiled code, I then load the source
file icicles-mcmd.el, then there is no crash.  That is the file that defines
`icicle-mouse-choose-completion', to which `mouse-choose-completion' is
defaliased (in Icicle mode).  I also traced that in the debugger after loading
that source file, and the event passed to `mouse-choose-completion' is a
legitimate mouse event (not nil nil as in the backtrace below).  Call me
clueless now.

Thinking that maybe the problem with these latest crashes was perhaps, after
all, that I was using an Emacs-20 byte-compiled icicles-mcmd.el, I byte-compiled
that file using Emacs 24 - and it still crashed (same way).  So for this file
too, the particular byte-compiler makes no difference.  So there are now two
ways to avoid the recent crash: load source file fit-frame.el or load source
file icicles-mcmd.el.  

I really don't understand (but then, I also don't understand the Lisp error
raised in the debugger (only) below).

Dunno if any of this makes sense anymore.  Sorry.


Debugger entered--Lisp error: (error "mouse-choose-completion must be bound to
an event with parameters")
call-interactively(mouse-choose-completion nil nil)

set-frame-size(minibuf frame 160 2)
frame-width(minibuf frame) -> 160
add-to-list(minor-mode-alist (icicle-mode " Icy"))
get-buffer-window("*Help*" 0) -> nil
set-face-background(region "MediumAquamarine")
recursion-depth() -> 1
frame-height(minibuf frame) -> 2
modify-frame-parameters(minibuf frame ((top . -28)))
frame-char-height -> 14
[fit-frame(minibuf frame) -> nil]
set-frame-size(minibuf frame 160 2)
[fit-frame-max-height -> 7]
fit-frame-thumbnail-factor(minibuf frame) -> 1
frame-char-height(minibuf frame) -> 14
x-display-pixel-height -> 1024
fit-frame-max-height(minibuf frame)
[fit-frame-max-frame-size -> (27 . 1)]
fit-frame-fringe-width(minibuf frame) -> 0
-> (27 . 1)
frame-parameters(minibuf frame)
window-frame(window 6) -> the minibuf frame
window-buffer() -> minibuf-1
select-window(window 6)
fit-frame-max-window-size(window 6) -> (27 . 1)
selected-window() -> window 6
select-frame(minibuf frame)
fit-frame-max-frame-size(minibuf frame)
next-window(window 6) -> window 6
selected-window() -> window 6 on minibuf
one-window-p(nil selected-frame)
select-frame(minibuf frame)
frame-parameters(minibuffer frame)
select-frame(the minibuf frame)
fboundp(image-mode-fit-frame) -> nil
fit-frame(the minibuffer frame)
frame-width(the minibuf frame) -> 160
minibuffer-prompt-end() -> 20
frame-height(the minibuffer frame) -> 2
(select-window save-selected-window-window) -> window 6
selected-frame() -> the minibuffer frame
select-window(window 6)
minibuffer-window -> window 6
selected-window -> window 6
(select-window save-selected-window-window) -> window 6
next-window(window 6) -> window 6
select-window(window 6)
one-window-p(nil selected-frame)
select-window(window 6)
minibuffer-window() -> window 6 on *Minibuf-1*
selected-window() -> window 6 on *Minibuf-1*
active-minibuffer-window() -> window 6 on *Minibuf-1*

reply via email to

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