diff --git a/bug-211314_p_drawable_privclean.diff b/bug-211314_p_drawable_privclean.diff new file mode 100644 index 0000000..420a8f6 --- /dev/null +++ b/bug-211314_p_drawable_privclean.diff @@ -0,0 +1,139 @@ +Novell Bugzilla #211314 and others +Maybe Xorg Bugzilla #7205 and probably others + + +Programs apparently crash if a context is reused for a window that changed in +the meantime. Crashes apparently only occure for software rendering. + +The basic problem is that a buffer is freed, when the according window is +closed, but the old context (which is no longer referenced in _glapi_Context +or in the according glxPriv structures) still has a reference to this buffer, +and is reactivated later. As the buffer points to a freed memory location, it +is no longer recognized as an old buffer (because buffer->Name - by accident - +contains 0x00cccccc) and not replaced. + + +About this patch: + +The correct way to remove the reference would be to nuke it when a context is +disassociated from a drawable - because after that only the Xserver itself +(and not the Mesa subsystem) knows about the context which still has the stray +buffer and glxPriv pointers. +Unfortunately, if you do that, the server crashes in glxSwapBuffers() - I +don't known enough about that code to decide, whether this is a broken +implementation, a bug in glxSwapBuffers() (there might be other calls), broken +by design, or deliberately chosen this way and actually correct. + +So the only way is to scan all contexts known for this client for references +to this buffer (and the according private structure) when the buffer is +actually destroyed. This is done in __glXMesaDrawableDestroy(), which has +access to all needed data - all but one. + +Scanning all contexts only needs the client id (which is known), but the API +call FindClientResourcesByType() actually needs a ClientPtr - just to extract +the client id! The ClientPtr is only known in glxext.c in a static array +__glXClients. I don't know of a different API to get the ClientPtr from, so I +exported it. One other possibility would be to add a ClientPtr fetch call to +glxext.c, another one to create a new FindClientIDResourcesByType(), another +one to create a Client structure with just the id included (ugh!) just for +this API call. Making the array extern was the simplest thing to do, but is +not necessarily the right solution. + +There is probably has a better / right possibility to remove all pointers to +the buffer (MakeCurrent2?) - but I don't have a better idea ATM. + +As I consider this a workaround / saveguard for some deeply involved buffer +handling bug, I added a lot of ErrorF()s that indicate these failures. If +removing these references at this point is the only valid solution, I'd gladly +remove these. As the scanning is only invoked on buffer destroys and doesn't +do a lot of scanning, performance is not an issue here. + +Matthias Hopf + + +--- GL/glx/glxext.c.orig 2007-01-23 16:00:19.000000000 +0100 ++++ GL/glx/glxext.c 2007-01-23 16:00:23.000000000 +0100 +@@ -59,7 +59,7 @@ xGLXSingleReply __glXReply; + ** A set of state for each client. The 0th one is unused because client + ** indices start at 1, not 0. + */ +-static __GLXclientState *__glXClients[MAXCLIENTS + 1]; ++__GLXclientState *__glXClients[MAXCLIENTS + 1]; + + /* + ** Forward declarations. + +--- GL/mesa/X/xf86glx.c.orig 2007-01-23 12:48:28.000000000 +0100 ++++ GL/mesa/X/xf86glx.c 2007-01-23 19:37:23.000000000 +0100 +@@ -95,12 +95,70 @@ static XMesaVisual find_mesa_visual(__GL + + + static void ++__glXMesaDrawableDestoryCB(pointer baseCtx, XID id, pointer basePriv) ++{ ++ __GLXMESAcontext *context = (__GLXMESAcontext *) baseCtx; ++ __GLXdrawable *glxPriv = (__GLXdrawable *) basePriv; ++ void *buffer =((__GLXMESAdrawable *) glxPriv) ->xm_buf; ++ __GLXMESAdrawable *drawPriv, *readPriv; ++ ++ if (context->base.drawPriv == glxPriv || ++ context->base.readPriv == glxPriv) { ++ ErrorF ("Cleaning up stray priv pointers to %p in context %p\n", ++ glxPriv, context); ++ if (context->base.drawPriv == glxPriv) ++ context->base.drawPriv = NULL; ++ if (context->base.readPriv == glxPriv) ++ context->base.readPriv = NULL; ++ } ++ drawPriv = (__GLXMESAdrawable *) context->base.drawPriv; ++ readPriv = (__GLXMESAdrawable *) context->base.readPriv; ++ if ((drawPriv && drawPriv->xm_buf == buffer) || ++ (readPriv && readPriv->xm_buf == buffer)) { ++ /* This should not happen, but the alternative is a sure server crash */ ++ ErrorF ("ERROR: Draw priv in context %p is not freed yet, " ++ "but has stray buffer pointer %p\n", context, buffer); ++ if (drawPriv && drawPriv->xm_buf == buffer) ++ drawPriv->xm_buf = NULL; ++ if (readPriv && readPriv->xm_buf == buffer) ++ readPriv->xm_buf = NULL; ++ } ++ if (context->xmesa && ++ (context->xmesa->mesa.DrawBuffer == buffer || ++ context->xmesa->mesa.ReadBuffer == buffer || ++ context->xmesa->mesa.WinSysDrawBuffer == buffer || ++ context->xmesa->mesa.WinSysReadBuffer == buffer || ++ context->xmesa->xm_buffer == buffer)) { ++ ErrorF ("Cleaning up stray xmesa pointers to buffer %p in context %p\n", ++ buffer, context); ++ if (context->xmesa->mesa.DrawBuffer == buffer) ++ context->xmesa->mesa.DrawBuffer = NULL; ++ if (context->xmesa->mesa.ReadBuffer == buffer) ++ context->xmesa->mesa.ReadBuffer = NULL; ++ if (context->xmesa->mesa.WinSysDrawBuffer == buffer) ++ context->xmesa->mesa.WinSysDrawBuffer = NULL; ++ if (context->xmesa->mesa.WinSysReadBuffer == buffer) ++ context->xmesa->mesa.WinSysReadBuffer = NULL; ++ if (context->xmesa->xm_buffer == buffer) ++ context->xmesa->xm_buffer = NULL; ++ } ++} ++ ++extern __GLXclientState *__glXClients[]; ++static void + __glXMesaDrawableDestroy(__GLXdrawable *base) + { + __GLXMESAdrawable *glxPriv = (__GLXMESAdrawable *) base; ++ ClientPtr client = __glXClients[CLIENT_ID(base->drawId)]->client; + +- if (glxPriv->xm_buf != NULL) ++ if (glxPriv->xm_buf != NULL) { ++ /* There may still be stray pointers in contexts that are no longer ++ * visible to Mesa. Scan all contexts for this client and nuke those ++ * pointers */ ++ FindClientResourcesByType(client, __glXContextRes, ++ __glXMesaDrawableDestoryCB, glxPriv); + XMesaDestroyBuffer(glxPriv->xm_buf); ++ } + xfree(glxPriv); + } + diff --git a/xorg-x11-server.changes b/xorg-x11-server.changes index 8c01760..f888425 100644 --- a/xorg-x11-server.changes +++ b/xorg-x11-server.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +Wed Jan 24 18:01:06 CET 2007 - sndirsch@suse.de + +- bug-211314_p_drawable_privclean.diff: + * fixes Xserver crash in Mesa software rendering path (Bug #211314) + ------------------------------------------------------------------- Tue Jan 23 11:45:28 CET 2007 - sndirsch@suse.de diff --git a/xorg-x11-server.spec b/xorg-x11-server.spec index 621b3f2..c6a6833 100644 --- a/xorg-x11-server.spec +++ b/xorg-x11-server.spec @@ -21,7 +21,7 @@ BuildRequires: libjpeg-devel URL: http://xorg.freedesktop.org/ %define EXPERIMENTAL 0 Version: 7.2 -Release: 45 +Release: 46 License: X11/MIT BuildRoot: %{_tmppath}/%{name}-%{version}-build Group: System/X11/Servers/XF86_4 @@ -80,6 +80,7 @@ Patch40: 0018-vnc-support.txt.diff Patch41: loadmod-bug197195.diff Patch42: bug227111-ddc_screensize.diff Patch43: bug-211314_mesa-context.diff +Patch44: bug-211314_p_drawable_privclean.diff Patch334: p_pci-domain.diff Patch357: p_pci-ce-x.diff @@ -172,6 +173,7 @@ popd %patch42 -p1 pushd ../Mesa %patch43 -p0 +%patch44 -p0 popd %build @@ -496,6 +498,9 @@ exit 0 %endif %changelog -n xorg-x11-server +* Wed Jan 24 2007 - sndirsch@suse.de +- bug-211314_p_drawable_privclean.diff: + * fixes Xserver crash in Mesa software rendering path (Bug #211314) * Tue Jan 23 2007 - sndirsch@suse.de - xserver 1.2.0 release * Bug #9219: Return BadMatch when trying to name the backing