Subject: fvwm crashes when using dynamic menus

From: Uwe Pross <[email-masked]>
Date: Sat, 20 Jul 2002 13:17:49 +0200

Hi there,

Yesterday I realized a reproducable crash of fvwm 2.5.2 and X when
using a menu which is created by fvwm-menu-directory:

DestroyFunc FuncFvwmMenuDirectory
AddToFunc FuncFvwmMenuDirectory I PipeRead "fvwm-menu-directory \
  --icon-dir=mini_filesystems.folder.xpm \
  --icon-file=mini_filesystems.File.xpm  \
  --icon-app=mini_filesystems.exec.xpm $1 --exec-file=jed --dir=$0"

DestroyMenu myFileBrowserMenu
AddToMenu myFileBrowserMenu "File Browser" Title
+ MissingSubmenuFunction FuncFvwmMenuDirectory
+ "Files"       Popup $[HOME]
+ "Files (All)" Popup $[HOME] "--all"

fvwm does not crash immediately. When using the menu above repeatedly
and using other menus between them it crashes. I could reproduce this
behavior several times.

I used gdb to see where the crash comes from. The output of gdb which
contains the stack trace after the crash is attached to this mail.

Linux Kernel 2.4.17
XFree86 Version 3.3.6
GNU gdb 5.0

Uwe
-- 
+----------------------------------------------
| Uwe Pross
| mail : mailto:[email-masked]
| www  : http://www.tu-chemnitz.de/~uwp
+----------------------------------------------

Have a nice day ;-).

-----------------------------------------------

---

From: Dominik Vogt <[email-masked]>
Date: Sat, 20 Jul 2002 22:12:27 +0200

> contains the stack trace after the crash is attached to this mail.

I think I've already fixed this one in poost-2.5.2 CVS.  Could
you please try a current snapshot?

Bye

Dominik ^_^  ^_^

 --
Dominik Vogt, [email-masked]
Reply-To: [email-masked]

--
Visit the official FVWM web page at <URL:http://www.fvwm.org/>.
To unsubscribe from the list, send "unsubscribe fvwm-workers" in the
body of a message to [email-masked].
To report problems, send mail to [email-masked]

---

From: Uwe Pross <[email-masked]>
Date: Wed, 24 Jul 2002 09:30:31 +0200

> you please try a current snapshot?

I have tried it today with fvwm-snap-20020723 but still the same. I
open the file menu looking through a couple of directories and switch
to another menu entry afterwards:

----------------------------------------------------------------------
GNU gdb 5.0
Copyright 2000 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB.  Type "show warranty" for details.
This GDB was configured as "i386-suse-linux"...
[tcsetpgrp failed in terminal_inferior: Inappropriate ioctl for device]
[tcsetpgrp failed in terminal_inferior: Inappropriate ioctl for device]
[tcsetpgrp failed in terminal_inferior: Inappropriate ioctl for device]
[tcsetpgrp failed in terminal_inferior: Inappropriate ioctl for device]
FvwmTheme is obsolete, see the Colorset section of the fvwm(1) man page
nelix being added to access control list
INFO: imwheel started (pid=11553)
Starting xterm -geometry 105x36+0+0...
Starting xemacs -geometry 111x43+0+1320...

Program received signal SIGSEGV, Segmentation fault.
0x8052f7f in paint_menu (mr=0x8156e98, pevent=0x80c0940, fw=0x0)
    at menus.c:4117
4117			if ((MST_FACE(mr).type != SolidMenu &&
#0  0x8052f7f in paint_menu (mr=0x8156e98, pevent=0x80c0940, fw=0x0)
    at menus.c:4117
#1  0x8055aa0 in menu_expose (event=0x80c0940, fw=0x0) at menus.c:6186
#2  0x804f726 in MenuInteraction (pmp=0xbffff004, pmret=0xbfffeff4, 
    pdkp=0xbfffef40, pdo_warp_to_title=0x80bda18) at menus.c:1849
#3  0x805574e in do_menu (pmp=0xbffff004, pmret=0xbfffeff4) at menus.c:6048
#4  0x809c736 in menu_func (cond_rc=0x0, eventp=0x80c0940, w=38, fw=0x0, 
    context=8, action=0x815587d "   WORK_MENU_popup Nop", Module=0xbffff1a0, 
    fStaysUp=1) at menucmd.c:142
#5  0x809c7dc in CMD_Menu (cond_rc=0x0, eventp=0x80c0940, w=38, fw=0x0, 
    context=8, action=0x815587d "   WORK_MENU_popup Nop", Module=0xbffff1a0)
    at menucmd.c:166
#6  0x807eafc in execute_function (efa=0xbffff188) at functions.c:915
#7  0x807ec71 in old_execute_function (cond_rc=0x0, 
    action=0x8144460 "Menu    WORK_MENU_popup Nop", fw=0x0, eventp=0x80c0940, 
    context=8, Module=-1, exec_flags=0, args=0x0) at functions.c:1000
#8  0x806e23e in HandleButtonPress () at events.c:582
#9  0x807158a in DispatchEvent (preserve_Fw=0) at events.c:3239
#10 0x8071620 in HandleEvents () at events.c:3294
#11 0x80855b4 in main (argc=1, argv=0xbffff6e4) at fvwm.c:741
#12 0x401c9baf in __libc_start_main () from /lib/libc.so.6
X Error of failed request:  BadDrawable (invalid Pixmap or Window parameter)
  Major opcode of failed request:  62 (X_CopyArea)
  Resource id in failed request:  0x3000002
  Serial number of failed request:  209
  Current serial number in output stream:  209
X connection to :0.0 broken (explicit kill or server shutdown).
xterm:  fatal IO error 32 (Broken pipe) or KillClient on X server ":0.0"
----------------------------------------------------------------------

Uwe

Have a nice day ;-).

---

From: Dominik Vogt <[email-masked]>
Date: Wed, 24 Jul 2002 10:52:21 +0200

> to another menu entry afterwards:

I can't reproduce the problem.  Please try to reduce your config
as much as possible and find step-by-step instructions.

Bye

Dominik ^_^  ^_^

 --
Dominik Vogt, mail: [email-masked], phone: 0721/91374-382
Schlund + Partner AG, Erbprinzenstr. 4-12, D-76133 Karlsruhe
--
Visit the official FVWM web page at <URL:http://www.fvwm.org/>.
To unsubscribe from the list, send "unsubscribe fvwm-workers" in the
body of a message to [email-masked].
To report problems, send mail to [email-masked]

---

From: Uwe Pross <[email-masked]>
Date: Wed, 24 Jul 2002 22:16:20 +0200

On Wed, Jul 24, 2002 at 03:38:56PM +0200, Dominik Vogt wrote:
> 
> I'm almost sure that this problem is related to multiple menu
> styles.  It never happened to me while I was using the default
> menu style only, but I could provoke a crash twice when I defined
> a new menu style for the root menu.

It is good to hear that it is reproducible outside of my computer. 

> You can run a separate X server or an Xnest in a window.
> ....
> To run fvwm in an Xnest window (Xnest should run on any X server):
> 
>   $ Xnest -full -sync -name "Xnest :3" -fp `xset -q | grep fonts` :3            
>   $ fvwm2 -d :3 ...

Thanks for the hints. I like the Xnest program it is quite funny to
see a fvwm running inside of fvwm ;-) 
Debugging is much easier that way as well.

> However, the biggest problem at hand is to reproduce the problem
> at will.  As long as it happens at a random time in a function
> that just accesses memory that was corrupted somewhere else, the
> core dumps are not very helpful.

That's the point. Meanwhile I found three positions in file menus.c
where a segmentation fault occured. But this posititions are not the
reason for the memory corruption. 

However I have to stop here since at the moment I am quite busy with
my study, so I can't help finding this little bug. Hopefully in
september I will have more time to work on some patches.  For me I
have disabled the dynamic menu since I hardly used it.

Uwe

Have a nice day ;-).

---

From: Dominik Vogt <[email-masked]>
Date: Thu, 25 Jul 2002 10:40:48 +0200

> reason for the memory corruption. 

I've seen two yet.  They have in common that an invalid menu style
is accessed, for example via (from paint_menu()):

  MenuStyle *ms = MR_STYLE(mr);

This expands to

  MenuStyle *ms = mr->ms->s;

Bye

Dominik ^_^  ^_^

---

From: Uwe Pross <[email-masked]>
Date: Thu, 25 Jul 2002 11:11:50 +0200

>   MenuStyle *ms = mr->ms->s;

That's right two occured in function 

static void paint_menu(
       MenuRoot *mr, XEvent *pevent, FvwmWindow *fw)
[line 4056 im menus.c]

one in line 4063:

      int bw = MST_BORDER_WIDTH(mr); 

another in line 4117:

      if ((MST_FACE(mr).type != SolidMenu &&
           MST_FACE(mr).type != SimpleMenu &&
           !MST_HAS_MENU_CSET(mr)) ||

In both cases *mr is involved.  I am quite sure that I checked if the
pointer mr or its subpointers were NULL before accessing it to prevent
the seg fault. This check was passed but the seg fault did still
occur. Maybe one of the pointer is not NULL but points to an invalid
segment (However this can happen). I will do a double check of this
test tonight or tommorow.

The third one occured in another function in menus.c. Unfortunately I
can't remember where it was. Maybe it happens again.

Uwe
-- 
+--------------------------------------------------
| Uwe Pross 
|   mailto:[email-masked]
|   http://www.tu-chemnitz.de/~uwp
+--------------------------------------------------
--
Visit the official FVWM web page at <URL:http://www.fvwm.org/>.
To unsubscribe from the list, send "unsubscribe fvwm-workers" in the
body of a message to [email-masked].
To report problems, send mail to [email-masked]

---

From: Dominik Vogt <[email-masked]>
Date: Thu, 25 Jul 2002 12:00:48 +0200

On Thu, Jul 25, 2002 at 11:11:50AM +0200, Uwe Pross wrote:
> In both cases *mr is involved.

If you look closely you can see that mr->ms->s is involved in all
cases (the static part of the menu style).  Mikhael posted a
similar core dumps a few weeks ago.  In his and one of the similar
crashes I got, the contents of mr->ms had been overwritten with
random data, so mr->ms->s pointed to a random location.

> I am quite sure that I checked if the

Bye

Dominik ^_^  ^_^

---

From: Uwe Pross <[email-masked]>
Date: Thu, 25 Jul 2002 21:42:12 +0200

> random data, so mr->ms->s pointed to a random location.

Sounds to me like a needle in a haystack ;-)

I played a little bit around and found the three locations
below where a seg fault occured. Meanwhile I am well trained in
provoking one of the seg faults ;-)
I am not that sure anymore that they have a common source. I inserted
some debug statements in menus.c in function paint_menu to see the
locations of the pointer which may cause the violation. The pointers
are printed out three times to see if they were changed inside the
function. 

To understand the following lines here is the printf-command:
fprintf(stderr,"1. mr = %d %d %d\n",(mr),(mr->s),(mr->s->ms));
----------------------------------------------------------------------

1. location and output

menus.c:4064

1. mr = 135959280 135978328 135139680
2. mr = 135959280 135978328 135139680
3. mr = 135959280 135978328 135139680
1. mr = 135312000 135316008 135139680
2. mr = 135312000 135316008 135139680
3. mr = 135312000 135316008 135139680
1. mr = 135959280 135960248 209
                            ^^^
This case is clear. The pointer mr->s->ms points to nirvana. This is
the case you described, Dominik.
----------------------------------------------------------------------

2. location and output

menus.c:4141
  if ((MST_FACE(mr).type != SolidMenu &&
3. mr = 135843984 135749536 135139680
1. mr = 135836320 135836336 135139680
2. mr = 135836320 135836336 135139680
3. mr = 135836320 135836336 135139680
1. mr = 135843984 135749536 135139680
1. mr = 135836320 135836336 135139680
2. mr = 135836320 135836336 135139680
3. mr = 135836320 135836336 135139680

The last debug statement was printed out shortly before the seg fault
occured. But all pointers seem to be normal :-| Actually no idea what
happend here.
This case happens most times.
----------------------------------------------------------------------

3. location and output

menuitem.c:320
  y_offset = MI_Y_OFFSET(mi);

This statement is called from the position where the previous seg
fault occured. So it may go away if the reason for the previous seg
fault is found.
----------------------------------------------------------------------

Any further ideas?

Uwe

---

From: Dan Espen <[email-masked]>
Date: Thu, 25 Jul 2002 15:50:18 -0400

> Sounds to me like a needle in a haystack ;-)

Usually Purify is good at finding those needles.

If I knew what Fvwm features you were exercising, I might
find some time to do a Solaris build and Purify run.
I need config file statements, and actions to perform.

-- 
Dan Espen                           E-mail: [email-masked]
444 Hoes Lane  Room RRC 1C-214      Phone: (732) 699-5570
Piscataway, NJ 08854
--
Visit the official FVWM web page at <URL:http://www.fvwm.org/>.
To unsubscribe from the list, send "unsubscribe fvwm-workers" in the
body of a message to [email-masked].
To report problems, send mail to [email-masked]

---

From: Uwe Pross <[email-masked]>
Date: Fri, 26 Jul 2002 08:36:02 +0200

> I need config file statements, and actions to perform.

I am not sure if purify can help here.

Original message: 
  http://www.hpc.uh.edu/fvwm/archive/0207/msg00373.html

The is a memory violation in function paint_menu which is file menus.c
about line 4100. This violation occurs randomly, which doesn't make it
easier ;-), when using  dynamic  menus  together  with  mutliple  menu
styles.  As  far as we found out yet there are two lines in paint_menu
where a voilation occurs. Those two may or may not caused by the  same
problem.  Common is both locations that the pointer sequence mr->s->ms
is accessed. In my last  mail  I  posted  the  values  of  this  three
pointers  shortly  before the crash. The second case I described shows
that the contents of mr->s->ms point to a wrong location. 
The first case I described seems a little bit  odd  to  me  since  the
three pointers seem to have proper values. 

Even I had a look  in  menus.h  where  the  struct  MenuRootStatic  is
described.  In  this  stucture there is a declaration Pixel sideColor;
before  the  declaration  MenuStyle  *ms;.  If  the  pointer  *ms   is
overwritten by accident it may be done by a overflow in this sideColor
variable. To check this one could insert a char array between the  two
declaration  and  watch  this.  If  this is the case the overflow will
affect the char array which otherwise should  be  never  accessed.  If
nothing  comes  out  in  this  case  today  I will probably do this at
weekend. 

Uwe

---

From: Dominik Vogt <[email-masked]>
Date: Fri, 26 Jul 2002 11:43:48 +0200

> provoking one of the seg faults ;-)

So, please post the responsible config file and describe exactly
what you are doing to provoke it.  Since exposing a menu is part
of one of the core dumps, the problem may even be related *where*
you open the menus (they bounce off the right side and may overlap
their grandparents).  Running Purify does not make much sense
without this information.  The only info I have is that dynamic
menus (MissingSubmenuFunc) and multiple menu styles are involved.
It may be necessary that the autogenerated menus destroy
themselves after use.

> fprintf(stderr,"1. mr = %d %d %d\n",(mr),(mr->s),(mr->s->ms));
...
> 1. mr = 135959280 135960248 209

Look closely:  it's not the mr->s->ms pointer that was trashed.
The mr->s pointer changed between the two invocations.  This must
not happen unless the menu style was changed.
contains trash

> the case you described, Dominik.
...
> This case happens most times.

Could be an attempt to access freed memory.

So, more evidence for some code overwriting random data?

> Any further ideas?

Yes.  Scatter these debug statements all over the
MenuInteraction() function.  We might be able to hunt down the
statement that overwrites the mr->s pointer this way.  I'll commit
a debug patch for this shortly.

Bye

Dominik ^_^  ^_^

---

From: Uwe Pross <[email-masked]>
Date: Fri, 26 Jul 2002 13:43:29 +0200

> It may be necessary that the autogenerated menus destroy

I thought you have reproduced the crash already. I am at the
university now and I don't have the responsible config here. I will
post it together with a description tonight or tommorow.  

> not happen unless the menu style was changed.

So I do not change menu styles. But the pointer mr->s changes
frequently and 135960248 seems to be a proper value. I will have a
double check of this.

> > The last debug statement was printed out shortly before the seg
> > fault occured. But all pointers seem to be normal :-| Actually no
> > idea what happend here.

That would be an explanation.  According to my experience one can
access freed memory without a segfault. An often made programmer
mistake is to access memory which was alloced locally by a function
and freed after its return. This happens to work in most cases.

> a debug patch for this shortly.

I will do some further checks. Maybe I am lucky ;-)

Uwe

---

From: Dominik Vogt <[email-masked]>
Date: Fri, 26 Jul 2002 13:53:35 +0200

> fprintf(stderr,"1. mr = %d %d %d\n",(mr),(mr->s),(mr->s->ms));

They have all one thing in common:  they are triggered
asynchronously by an expose event.  Somehow I managed to delete
the menu structure while the X server still stored the connection
between the structure and the window.  When an expose event
arrived, fvwm queried the X server for an associated menu
structure and got the address of the deleted one.  This was caused
by some funny interaction between the Display used to create the
menu and the one that created the context.  I'm puzzled how this
could happen:

  XDestroyWindow(menu_display, menu_window, ...);
  XFlush(menu_display);
  XDeleteContext(normal_display, menu_context, ...);
  ...
  (Expose event arrives)
  XFindContext(normal_diplay, event_window, ...);

So, the XFindContext after the XDeleteContext returned the already
deleted context.  It seems that those two calls are not strictly
serialized on the server.

I have committed a fix along with a lot of temporary debug code
that creates a core dump when an inconsistent menu structure is
detected.

Bye

Dominik ^_^  ^_^

---

From: Dominik Vogt <[email-masked]>
Date: Fri, 26 Jul 2002 14:11:47 +0200

On Fri, Jul 26, 2002 at 01:43:29PM +0200, Uwe Pross wrote:
> frequently and 135960248 seems to be a proper value.

I have to correct myself:  It must *never* happen.  The 's' bit is
not the menu style but the static part of the menu structure.
This is never changed while the menu exists.

> I will have a double check of this.
> 
> access freed memory without a segfault.

Even moreso because the memory often gets allocated again almost
instantly and is filled with new data.

> An often made programmer

(with my bugfix, I hope).  Before the fix, the crash could be
provoked like this:

 1) Open the root menu.
 2) Open a directory menu from the root menu.
 3) Hierarchically open submenus of the directory menu until one
    of these menus overlaps a different directory menu.
 4) Move the pointer back to the root menu without passing over
    any other menu (this can be tricky).

=> The submenus are closed and destroyed.  The partially hidden
   menu gets an Expose event - after it was destroyed.
=> Boom!

Bye

Dominik ^_^  ^_^

---

From: Uwe Pross <[email-masked]>
Date: Fri, 26 Jul 2002 22:21:18 +0200

> > post it together with a description tonight or tommorow.  

I think you have found it already. Just in case I put the config on
the net http://www.tu-chemnitz.de/~uwp/download/fvwm2rc_menu_problem
My desciption is would have been similar to the one you gave below.

Uwe