Bug 24576 - SegFault - FreePicture - dixFreePrivates - memset
Summary: SegFault - FreePicture - dixFreePrivates - memset
Status: RESOLVED FIXED
Alias: None
Product: xorg
Classification: Unclassified
Component: Server/DDX/dmx (show other bugs)
Version: git
Hardware: x86 (IA32) Linux (All)
: high normal
Assignee: dmx-bugs
QA Contact: Xorg Project Team
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2009-10-16 12:35 UTC by Lee Leahu
Modified: 2009-10-21 07:40 UTC (History)
2 users (show)

See Also:
i915 platform:
i915 features:


Attachments
valgrind output - plain Xorg (301.57 KB, text/plain)
2009-10-19 11:40 UTC, Lee Leahu
no flags Details
valgrind output - Xorg + Xdmx (203.02 KB, text/plain)
2009-10-19 11:41 UTC, Lee Leahu
no flags Details
fprintf-debugging-statements.patch (5.29 KB, text/plain)
2009-10-19 11:42 UTC, Lee Leahu
no flags Details
dmxDestroyWindow() - must call the X's native DetroyWindow() (1.11 KB, patch)
2009-10-19 13:45 UTC, Lee Leahu
no flags Details | Splinter Review

Description Lee Leahu 2009-10-16 12:35:00 UTC
Environment:
 xorg-server - GIT Commit - 25344ba7f7845654364d62bf15322b3b79465bd9
 2 Computers
     First computer runs X Backend and Xdmx
     Second computer runs kpersonalizer with it's DISPLAY variable set to the first machine's :1.

On the first machine:
  Backend X is started with:
    X :0 -ac

  Xdmx is started with:
    Xdmx :1 -ac +xinerama -display :0 -input :0

On the second machine:
  export DISPLAY=firstmachine:1
  kpersonalizer

At this point kpersonalizer will display in Xdmx and function normally.  Click next through all the screens until the last screen with the Finish button.

Click the Finish button, the window will disappear and Xdmx will segfault.



Program received signal SIGSEGV, Segmentation fault.
0x08192a4d in privateExists (privates=0x6503c4cc, key=0x8229440) at privates.c:79
79          return *key && *privates &&
(gdb) bt
#0  0x08192a4d in privateExists (privates=0x6503c4cc, key=0x8229440) at privates.c:79
#1  0x081929e4 in dixLookupPrivate (privates=0x6503c4cc, key=0x8229440) at privates.c:162
#2  0x080c922c in FreePicture (value=0x8817d10, pid=2097797) at picture.c:1547
#3  0x08198587 in FreeClientResources (client=0x880a708) at resource.c:812
#4  0x08173a15 in CloseDownClient (client=0x880a708) at dispatch.c:3637
#5  0x0816b56c in Dispatch () at dispatch.c:430
#6  0x0815e1c1 in main (argc=8, argv=0xbfa03954, envp=0xbfa03978) at main.c:285
Comment 1 Lee Leahu 2009-10-17 19:46:51 UTC
A simpler test is to start kpersonalizer as prescribed, but then CTRL-C the application just after it displays - no specific timing required.  No need to interact with the displayed application either.
Comment 2 Lee Leahu 2009-10-18 14:21:45 UTC
I've narrowed this down further.

Once kpersonalizer is fully running and waiting for user input, the following data structure is populated with this data:

((PicturePtr)clientTable[1].resources[181]->value)->pDrawable->pScreen: 139601136

After hitting CTRL-C, Xdmx begins to cleanup the memory used to display that app.

At the point of interest, it gets down into AllocateGlyphHash():

#0  AllocateGlyphHash (hash=0xbf930e6c, hashSet=0x821da98) at glyph.c:462
#1  0x080c25dc in ResizeGlyphHash (hash=0x822b418, change=0, global=1) at glyph.c:495
#2  0x080c2a04 in FreeGlyphSet (value=0x87f68a0, gid=2097172) at glyph.c:589
#3  0x08199458 in FreeClientResources (client=0x87e6708) at resource.c:874
#4  0x081743bc in CloseDownClient (client=0x87e6708) at dispatch.c:3648
#5  0x0816be5c in Dispatch () at dispatch.c:430
#6  0x0815eab3 in main (argc=8, argv=0xbf931094, envp=0xbf9310b8) at main.c:288

Within that function is the call to xcalloc:
    hash->table = xcalloc (hashSet->size, sizeof (GlyphRefRec));

Immediately before this call, the data is as expected:
((PicturePtr)clientTable[1].resources[181]->value)->pDrawable->pScreen: 139601136

Immediately after this call, the data is nulled out:
((PicturePtr)clientTable[1].resources[181]->value)->pDrawable->pScreen: 0


Comment 3 Lee Leahu 2009-10-18 15:16:44 UTC
Even more interesting:

Just before that call to xcalloc, hash->table was pointing to the memory location 0x80c205f.

Just after that call to xcalloc, hash->table is now pointing to the memory location 0x8f9c1f0.

What makes this interesting is this structure:
((PicturePtr)clientTable[1].resources[181]->value)->pDrawable->pScreen:

The location for pScreen (&...->pScreen) that holds the pointer to the pScreen data is 0x8f9c658.

Now here's the stinker:

That call to xcalloc requested 1208 bytes of memory.  malloc returned 1208 bytes of memory starting at 0x8f9c1f0.   Doing the math 0x8f9c1f0 + 1208 = 0x8f9c6a8.

If I understand the problem correctly, the pointer to the pScreen data for that picture is being overwritten by the xcalloc call.
Comment 4 Lee Leahu 2009-10-18 15:33:56 UTC
A thought occured to be over dinner... Perhaps xcalloc() is working correctly, and that memory location was already freed.

Ran it through valgrind and sure enough, that's the case.

I'll go back and re-check where the free() occurs... 
Comment 5 Lee Leahu 2009-10-19 06:27:06 UTC
It seems that (...->pScreen) is being deleted early on during FreeClientResources(), but then needed later for a call by FreePicture(), also in FreeClientResources().

Initially I thought a quick workaround might be to add a if(!pScreen) to FreePicture(), but seeing how that memory has already been freed - there's no guarantee that (...->pScreen) will be 0x0.

Comment 6 Lee Leahu 2009-10-19 11:40:07 UTC
Ahah!

After adding some specific fprintf() statements to DeleteWindow, CrushTree, and Xfree(), a clear picture of what's going on is forming:

If Xorg is run w/o Xdmx, and kpersonalizer displayed to that, there are 97 calls to Xfree() from DeleteWindow()->CrushTree().

Additionally, there are calls to FreePicture() before 6 of those Xfree()'s.

Comparing that to when Xorg is run w/ Xdmx, and kpersonalizer displayed to Xdmx, there are still 97 calls to Xfree() from the same location.

However, there are no calls to FreePicture() before those 6 Xfree()'s.

I'll attach the output from valgrind from running the plain Xorg  and the Xorg + Xdmx.  I'll also attach a diff of the changes made in case anyone wants to duplicate.
Comment 7 Lee Leahu 2009-10-19 11:40:48 UTC
Created attachment 30565 [details]
valgrind output - plain Xorg 

kpersonalizer displaying to plain Xorg

# X :0 -ac
Comment 8 Lee Leahu 2009-10-19 11:41:38 UTC
Created attachment 30566 [details]
valgrind output - Xorg + Xdmx

kpersonalizer displaying to Xdmx

# X :0 -ac
# Xdmx :1 -ac +xinerama -display :0
Comment 9 Lee Leahu 2009-10-19 11:42:12 UTC
Created attachment 30567 [details]
fprintf-debugging-statements.patch
Comment 10 Lee Leahu 2009-10-19 13:45:36 UTC
Created attachment 30570 [details] [review]
dmxDestroyWindow() - must call the X's native DetroyWindow()

Problem solved!  dmxDestroyWindow wasn't calling X's DestroyWindow().

Here is the patch that fixes this bug.
Comment 11 Peter Hutterer 2009-10-19 22:37:36 UTC
Patch merged into http://cgit.freedesktop.org/~whot/xserver/

Thanks for your work, your effort is much appreciated. I'll close this bug once it hits master.
Comment 12 Lee Leahu 2009-10-21 07:40:24 UTC
Closing

Patch commited to git master as f713f447a2110718dfc091380699362d76f0cd6c.


Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.