Subject: Core dump during purify test

From: "Paul D. Smith" <[email-masked]>
Date: Wed, 18 Nov 1998 17:05:09 -0500 (EST)

Here's the stack trace:

    ...
[FVWM][ProcessNewStyle]: <<ERROR>> bad style command: style "*" NoOverride

[FVWM][move_window_doit]: <<ERROR>> MoveToPage: invalid page number

Program received signal SIGSEGV, Segmentation fault.
0x616b4 in Destroy (Tmp_win=0xe89e8) at ../../fvwm/fvwm/misc.c:182
182       Tmp_win->stack_prev->stack_next = Tmp_win->stack_next;

(gdb) bt
#0  0x616b4 in Destroy (Tmp_win=0xe89e8) at ../../fvwm/fvwm/misc.c:182
#1  0x3c340 in destroy_function (eventp=0xa1000, w=4194780, tmp_win=0xe89e8, 
    context=1, action=0x1d9660 ".mwq.-l km<F3>noiDestroy .mwq.-l km<F3>noi", 
    Module=0xeffff41c) at ../../fvwm/fvwm/builtins.c:738
#2  0x4f848 in ExecuteFunction (Action=0x1 <Address 0x1 out of bounds>, 
    tmp_win=0xe89e8, eventp=0xa1238, context=1, Module=-2)
    at ../../fvwm/fvwm/functions.c:247
#3  0x46c7c in ComplexFunction (eventp=0xa1238, w=4013705316, tmp_win=0xe89e8, 
    context=1, 
    action=0x97959 "         (((((", ' ' <repeats 18 times>, "\210", '\020' <repeats 15 times>, "DDDDDDDDDD\020\020\020\020\020\020\020AAAAAA", '\001' <repeats 20 times>, "\020\020\020\020\020\020BBBBBB", '\002' <repeats 20 times>, "\020\020\020\020 ", Module=0xeffff5c4) at ../../fvwm/fvwm/complex.c:159
#4  0x4f848 in ExecuteFunction (Action=0x1 <Address 0x1 out of bounds>, 
    tmp_win=0xe89e8, eventp=0xa1238, context=1, Module=-1)
    at ../../fvwm/fvwm/functions.c:247
#5  0x4d144 in HandleButtonPress () at ../../fvwm/fvwm/events.c:1121
#6  0x4a140 in DispatchEvent () at ../../fvwm/fvwm/events.c:155
#7  0x4a1b4 in HandleEvents () at ../../fvwm/fvwm/events.c:176
#8  0x50de8 in main (argc=0, argv=0x9e800) at ../../fvwm/fvwm/fvwm.c:465

The problem is that Tmp_win appears to contain junk:

(gdb)  p *Tmp_win        
$5 = {next = 0x0, prev = 0x8104, stack_next = 0xef3b3a04, 
  stack_prev = 0xef3b2ea4, w = 4013466972, old_bw = -281262280, 
  frame = 4013705316, Parent = 201596, title_w = 311048, sides = {333532, 
    282072, 325696, 289908}, corners = {325696, 315708, 303416, 303532}, 
  nr_left_buttons = 331232, nr_right_buttons = 8292, left_w = {0, 4036513624,
    ...

A very suspicious comment appears above this code in Destroy():

  /*
      RBW - 11/13/1998 - new: have to unhook the stacking order chain also.
      There's always a prev and next, since this is a ring anchored on
      Scr.FvwmRoot
  */

Hmm... :)

But, that may not be the problem.  Something is going on here that has
Purify so confused it's generating bad data; here's the first really
serious (non-read related) report:

****  Purify instrumented /usr/local/pure/bin/fvwm2 (pid 14357)  ****
FMR: Free memory read:
  * This is occurring while in:
        ComplexFunction [complex.c:155]
        ExecuteFunction [functions.c:247]
        HandleButtonPress [events.c:1121]
        DispatchEvent  [events.c:155]
        HandleEvents   [events.c:176]
        main           [fvwm.c:465]
        start          [crt0.o]
  * Reading 4 bytes from 0xe8a00 in the heap.
  * Address 0xe8a00 is 24 bytes into a freed  block at 0xe89e8 of 508 bytes.
  * This block was allocated from:
        start          [crt0.o]
  * There have been -314681 frees since this block was freed.

Uh?  -314681 frees?  And allocated from "start" in crt0.o?  And no
traceback regarding where it was freed?  Usually with FMR you get a
trace on where it was used, where it was freed, _and_ where it was
allocated.

I'll send the entire Purify log but I'm not sure it'll be too
enlightening.

-- 
-------------------------------------------------------------------------------
 Paul D. Smith <[email-masked]>         Network Management Development
 "Please remain calm...I may be mad, but I am a professional." --Mad Scientist
-------------------------------------------------------------------------------
   These are my opinions---Nortel Networks takes no responsibility for them.
--
Visit the official FVWM web page at <URL:http://www.hpc.uh.edu/fvwm/>.
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: Bob Woodside <[email-masked]>
Date: Wed, 18 Nov 1998 22:27:16 -0500 (EST)

"Paul D. Smith" <[email-masked]> wrote:
>         [...]
>         [...]
> But, that may not be the problem.

	You scared me there, for a minute! But you're right, that's not the
problem. It would have segfaulted a couple of lines further down if my code
hadn't been there, because we're not looking at an FvwmWindow struct. From
the Purify log, I gather there's been a lot of looking at whatever it is,
before somebody invoked a Destroy command that tries to touch as well as
look.

>  Something is going on here that has
>         [...]
>         [...]

	Well, it's enlightening to the extent that it shows that somebody is
calling ExecuteFunction with a presumably uninitialized, non-null tmp_win
pointer; and that this seems to have been happening over and over. Whatever
was in this tmp_win pointer was probably never a valid address, and just
happens to evaluate to the address of a valid (but not for us) memory location.

	Have you been able to determine how far you got into the script, and
what sequence of commands/functions led up to this?

- Bob

---

From: [email-masked] (Paul D. Smith)
Date: 19 Nov 1998 10:01:05 -0500

%% Bob Woodside <[email-masked]> writes:

  bw> 	Have you been able to determine how far you got into the script, and
  bw> what sequence of commands/functions led up to this?

The fvwm log shows this just before the core:

  [FVWM][PipeRead]: <<ERROR>> missing parameter
  [FVWM][PipeRead]: <<ERROR>> missing parameter
  cat: /nonexistent/foo/bar: No such file or directory
  [FVWM][ProcessNewStyle]: <<ERROR>> IconGrid needs 2 numbers > 0. Got 2 numbers. x=-10 y=10!
  [FVWM][ProcessNewStyle]: <<ERROR>> bad style command: -10 10, IconFill

  [FVWM][ProcessNewStyle]: <<ERROR>> IconGrid needs 2 numbers > 0. Got 2 numbers. x=0 y=10!
  [FVWM][ProcessNewStyle]: <<ERROR>> bad style command: -0 10

  [FVWM][ProcessNewStyle]: <<ERROR>> bad StartsOnDesk arg: 

  [FVWM][ProcessNewStyle]: <<ERROR>> bad StartsOnPage args: 

It was moving windows around the screen when it died; it's hard to tell
exactly where in the fvwm2rc, but I'll try to get more info.

---

From: Dominik Vogt <[email-masked]>
Date: Thu, 19 Nov 1998 16:45:06 +0100

> exactly where in the fvwm2rc, but I'll try to get more info.

Unfortunately you don't get much information from this output other
than it fvwm has passed these commands before it cordumped. Although
I tried to test every command with invalid parameters not all of them
produce a message. I'd try a binary search to find the coredumping
command.

Bye

Dominik
-- 
Dominik Vogt, Hewlett-Packard GmbH, Dept. BVS
Herrenberger Str.130, 71034 Boeblingen, Germany
phone: 07031/14-4596, fax: 07031/14-3883, [email-masked]
--
Visit the official FVWM web page at <URL:http://www.hpc.uh.edu/fvwm/>.
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: Fri, 20 Nov 1998 13:18:06 +0100

I see it clear as day now:

The window is destroyed *twice*. The first call to Destroy
kills it, but before the tmp_win is deleted from the list
of windows Destroy() is called again (probably triggered
by an event in events.c). *crash*

Could someone describe how exactly fvwm2 is multitasked
or multithreaded? There must be a kind of locking mechanism
on the window list to prevent such bugs.

Bye

Dominik

---

From: Dominik Vogt <[email-masked]>
Date: Fri, 20 Nov 1998 16:40:23 +0100

> by an event in events.c). *crash*

To get the test running you can comment the Close/Delete/Destroy
lines.

Bye

Dominik

---

From: [email-masked] (Paul D. Smith)
Date: 20 Nov 1998 13:42:03 -0500

%% Dominik Vogt <[email-masked]> writes:

  dv> I see it clear as day now:
  dv> The window is destroyed *twice*. The first call to Destroy
  dv> kills it, but before the tmp_win is deleted from the list
  dv> of windows Destroy() is called again (probably triggered
  dv> by an event in events.c). *crash*

  dv> Could someone describe how exactly fvwm2 is multitasked
  dv> or multithreaded? There must be a kind of locking mechanism
  dv> on the window list to prevent such bugs.

Not sure what you mean here; AFAIK X apps _aren't_ multithreaded.  The
event loop is "run to completion" and ensures that one event completes
before the next one is invoked.  Isn't it?  I'm no X expert, that's for
damn sure.

If you mean that, _within_ an X event handling sequence, the window is
destroyed twice?  If that's the case, IMO it's just a coding error.

For example, perhaps the window should be removed from the list _first_,
before any other processing to destroy it is done?  Then if subsequent
processing tries to destroy a window that isn't found in the list, it
can just be ignored.  Or something.

I'll re-run the test with the latest code and let you know.  I'll remove
all the old objects and rebuild from scratch; maybe the Purify log will
be less "corrupted" this time.

---

From: Dominik Vogt <[email-masked]>
Date: Fri, 20 Nov 1998 19:57:56 +0100

> before the next one is invoked.  Isn't it?  I'm no X expert, that's for

Neither am I. I'm completely ignorant of X.

> destroyed twice?  If that's the case, IMO it's just a coding error.

Perhaps like this:

 1) Destroy called from a command from the config file
 2) 'Window destroyed' event arrives
 3) event code calls Destroy *again*

Commands invoked from the config file are not handled by the
event loop. Do we actually need to handle all events during startup?
Another idea is to change the command run in the xterm windows in
purify.fvwm2rc. I think if you use a shell instead of sleep this
coredump might not happen anymore.

> can just be ignored.  Or something.

Might work. Let's try it.

> be less "corrupted" this time.

If you're fast I can take the log home and work on it
during the weekend (you have 30 minutes :) )

Bye

Dominik

---

From: Brad Giaccio <[email-masked]>
Date: Fri, 20 Nov 1998 14:08:41 -0500 (EST)

> coredump might not happen anymore.

Here is how X likes to handle events.
You create your app 
You register to listen for events 
You start the main event loop

Now any events that happen be tween step 2 and step 3 get cued because you
told the xserver you wanted them.  So when you start your loop you get
values off the queue.  There is a event flush command you can call just
before you start the event loop which will probablly handle getting rid of
most events.  But you probably will find we want most of the events so
flushing isn't that good of an idea

> Might work. Let's try it.

This is the correct way to handle it. 

-- 
--- There are two kinds of knowledge, you either know the answer or
			you know where to find it
		      -Kane, Johnson, and anonymous

---

From: [email-masked] (Paul D. Smith)
Date: 20 Nov 1998 14:48:56 -0500

dv> Perhaps like this:

  dv>  1) Destroy called from a command from the config file
  dv>  2) 'Window destroyed' event arrives
  dv>  3) event code calls Destroy *again*

Yes, but I think that X doesn't interrupt your process.  X events aren't
like signals, they're like data on a filedescriptor (actually, they
usually _are_ data on a filedescriptor :).  Arriving X events, like
arriving data, are queued until you select() or whatever, then read(2)
them off (in this case, the X libraries do that for you).

So, X events should never _interrupt_, asynchronously, handling of
previous events.  That's how I understand it, anyway.

---

From: [email-masked] (Paul D. Smith)
Date: 20 Nov 1998 15:05:29 -0500

%% Brad Giaccio <[email-masked]> writes:

  >> > For example, perhaps the window should be removed from the list
  >> > _first_, before any other processing to destroy it is done?  Then
  >> > if subsequent processing tries to destroy a window that isn't
  >> > found in the list, it can just be ignored.  Or something.

  >> Might work. Let's try it.

  bg> This is the correct way to handle it. 

We can certainly change the code, but based on my reading of the latest
Purify logs, I just don't think this is the problem.  As I mentioned in
my post, it seems to me like fvwm thinks that something is a pointer to
an FvwmWindow structure when in fact it's nothing of the sort.

The fact that the pointer is allocated from within:

  * This block was allocated from:
        malloc         [rtlib.o]
        _XEnq          [libX11.so.4.30]
        _XReply        [libX11.so.4.30]
        XGetWindowProperty [libX11.so.4.30]
        XGetTextProperty [libX11.so.4.30]
        XGetWMName     [libX11.so.4.30]
        AddWindow      [add_window.c:635]
        HandleMapRequestKeepRaised [events.c:704]
        CaptureAllWindows [fvwm.c:612]
        Recapture      [builtins.c:4034]

leads me to believe it's really a WM_NAME property pointer--unless
Purify is _really_ confused.  One interesting thing is that the code in
HandleMapRequestKeepRaised() is:

  /* If the window has never been mapped before ... */
  if(!Tmp_win)
    {
      /* Add decorations. */
      Tmp_win = AddWindow(Event.xany.window);
      if (Tmp_win == NULL)
	return;
    }

One could easily imagine that this code is not executed all that often (?)

---

From: Bob Woodside <[email-masked]>
Date: Fri, 20 Nov 1998 23:31:59 -0500 (EST)

>   >> > found in the list, it can just be ignored.  Or something.

	I don't think this would buy us much (too bad Destroy doesn't
return a value, so the caller could check whether he made a boo-boo).
True, we could prevent a segfault by checking the list for a match on
Tmp_win (_first_, before referencing the Tmp_win pointer), but I think
this might just mask a bug that would be better squashed.

> an FvwmWindow structure when in fact it's nothing of the sort.

	I agree. As I said yesterday, I think somebody is simply passing
an uninitialized but non-null local variable (i.e., dirty memory on the
stack) as an FvwmWindow pointer. The trick is tracing back to whodunnit.

	Sorry I haven't had time to look into this more; it looks like it
could be quite an entertaining romp. Maybe this weekend, after I fix
StartsOnPage once more (naaahh, you'll probably have found it by then!)

- Bob

---

From: Bob Woodside <[email-masked]>
Date: Sun, 22 Nov 1998 13:44:34 -0500 (EST)

[email-masked] (Paul D. Smith) wrote:
> ...it seems to me like fvwm thinks that something is a pointer to

	This is strange. I can't duplicate this on my Linux system
(using a CVS build from Friday evening).

	I tried putting a little debugging code at the entry to Destroy,
which checks whether the Tmp_win pointer matches anything in the window
chain, and puts out a debugging message if not. Then I ran the Purify
script. No luck. The script runs to completion, no segfault, and no
bogus window pointers caught.

	I'm really stumped at this point.

	I'm beginning to wonder whether Purify *is* doing something
strange. Can you run the script without a segfault in a non-Purify
environment?

- Bob

---

From: Dominik Vogt <[email-masked]>
Date: Mon, 23 Nov 1998 11:28:49 +0100

> (using a CVS build from Friday evening).

That's why I released the script anyway. I don't get a coredump
on my Linux too.

Dominik

---

From: Dominik Vogt <[email-masked]>
Date: Mon, 23 Nov 1998 11:31:16 +0100

> an FvwmWindow structure when in fact it's nothing of the sort.

Whatever the bug may be, I have done this change. If this prevents the
coredump on your system and you want to further investigate you have to
move about 10 lines from the beginning of the Destroy function back to it's
old position (there were other changes in the file, so just using an old
copy might not work).

Bye

Dominik