<p dir="ltr">This scheme is copied from radeon, does it need a similar fix? I'm away from computers for another week or so, will be able to look then.</p>
<div class="gmail_quote">On Jun 5, 2015 4:37 PM, "Mario Kleiner" <<a href="mailto:mario.kleiner.de@gmail.com">mario.kleiner.de@gmail.com</a>> wrote:<br type="attribution"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">The dup'ed fd owned by the nouveau_screen for a device node<br>
must also be used as key for the winsys hash table, instead<br>
of using the original fd passed in for a screen, to make<br>
multi-x-screen ZaphodHeads configurations work on nouveau.<br>
<br>
This prevents the following crash scenario that was observed<br>
when a dynamically loaded rendering plugin used OpenGL on a<br>
ZaphodHeads setup, e.g., on a dual x-screen setup. At first<br>
load the plugin worked, but after unloading and reloading it,<br>
the next rendering operation crashed:<br>
<br>
1. Client, e.g., a plugin, calls glXQueryVersion.<br>
<br>
2. DRI screens for the x-screens 0 and 1 are created, one shared<br>
   nouveau_screen is created for the shared device node of both<br>
   screens, but the original fd of x-screen 0 is used as identifying<br>
   key in the hash table, instead of the dup()ed fd of x-screen 0<br>
   which is owned by the nouveau_screen. nouveau_screen's refcount<br>
   is now 2.<br>
<br>
3. Regular rendering happens by the client plugin, then the plugin<br>
   gets unloaded.<br>
<br>
4. XCloseDisplay(). x-screen 0 gets its DRI screen destroyed,<br>
   nouveau_drm_screen_unref() drops the refcount to 1, calling mesa<br>
   code then closes the fd of x-screen 0, so now the fd which is<br>
   used as key in the hash table is invalid. x-screen 1 gets<br>
   destroyed, nouveau_drm_screen_unref() drops the refcount to 0,<br>
   the nouveau_screen gets destroyed, but removal of its entry<br>
   in the hash table fails, because the invalid fd in the hash<br>
   table no longer matches anything (fstat() on the fd is used<br>
   for hashing and key comparison, but fstat() on an already closed<br>
   fd fails and returns bogus results). x-screen 1 closes its fd.<br>
<br>
   Now all fd's are closed, the nouveau_screen destroyed, but<br>
   there is a dangling reference to the nouveau_screen in the<br>
   hash table.<br>
<br>
5. Some OpenGL client plugin gets loaded again and calls<br>
   glXQueryVersion. Step 2 above repeats, but because a<br>
   dangling reference with a matching fd is found in the winsys<br>
   hash table, no new nouveau_screen is created this time. Instead<br>
   the invalid pointer to the old nouveau_screen is recycled,<br>
   which points to nirvana -> Crash.<br>
<br>
This problem is avoided by use of the dup()ed fd which is<br>
owned by the nouveau_screen and has the same lifetime as<br>
the nouveau_screen itself.<br>
<br>
Cc: "10.3 10.4 10.5 10.6" <<a href="mailto:mesa-stable@lists.freedesktop.org">mesa-stable@lists.freedesktop.org</a>><br>
<br>
Signed-off-by: Mario Kleiner <<a href="mailto:mario.kleiner.de@gmail.com">mario.kleiner.de@gmail.com</a>><br>
Cc: Ilia Mirkin <<a href="mailto:imirkin@alum.mit.edu">imirkin@alum.mit.edu</a>><br>
---<br>
 src/gallium/winsys/nouveau/drm/nouveau_drm_winsys.c | 3 ++-<br>
 1 file changed, 2 insertions(+), 1 deletion(-)<br>
<br>
diff --git a/src/gallium/winsys/nouveau/drm/nouveau_drm_winsys.c b/src/gallium/winsys/nouveau/drm/nouveau_drm_winsys.c<br>
index 0635246..dbc3cae 100644<br>
--- a/src/gallium/winsys/nouveau/drm/nouveau_drm_winsys.c<br>
+++ b/src/gallium/winsys/nouveau/drm/nouveau_drm_winsys.c<br>
@@ -120,7 +120,8 @@ nouveau_drm_screen_create(int fd)<br>
        if (!screen)<br>
                goto err;<br>
<br>
-       util_hash_table_set(fd_tab, intptr_to_pointer(fd), screen);<br>
+       /* Use dupfd in hash table, to avoid crashes in ZaphodHeads configs */<br>
+       util_hash_table_set(fd_tab, intptr_to_pointer(dupfd), screen);<br>
        screen->refcount = 1;<br>
        pipe_mutex_unlock(nouveau_screen_mutex);<br>
        return &screen->base;<br>
--<br>
2.1.4<br>
<br>
</blockquote></div>