diff options
author | Ben Skeggs <[email protected]> | 2015-11-26 14:34:43 +1000 |
---|---|---|
committer | Ben Skeggs <[email protected]> | 2015-12-22 13:24:05 +1000 |
commit | 323d4da372298900ce02293a682ba563ac29f4cb (patch) | |
tree | b1c88e2101f095fdff42e86c28d066313b297283 /src/gallium/winsys | |
parent | 6c1bfff66ca6dd9dac11507889ee17987bed31cb (diff) |
nouveau: fix screen creation failure paths
The winsys layer would attempt to cleanup the nouveau_device if screen
init failed, however, in most paths the pipe driver would have already
destroyed it, resulting in accesses to freed memory etc.
This commit fixes the problem by allowing the winsys to detect whether
the pipe driver's destroy function needs to be called or not.
Signed-off-by: Ben Skeggs <[email protected]>
Reviewed-by: Emil Velikov <[email protected]>
Reviewed-by: Samuel Pitoiset <[email protected]>
Tested-by: Samuel Pitoiset <[email protected]>
Diffstat (limited to 'src/gallium/winsys')
-rw-r--r-- | src/gallium/winsys/nouveau/drm/nouveau_drm_winsys.c | 16 |
1 files changed, 10 insertions, 6 deletions
diff --git a/src/gallium/winsys/nouveau/drm/nouveau_drm_winsys.c b/src/gallium/winsys/nouveau/drm/nouveau_drm_winsys.c index e117dfcd009..456530d7427 100644 --- a/src/gallium/winsys/nouveau/drm/nouveau_drm_winsys.c +++ b/src/gallium/winsys/nouveau/drm/nouveau_drm_winsys.c @@ -59,7 +59,7 @@ nouveau_drm_screen_create(int fd) { struct nouveau_device *dev = NULL; struct nouveau_screen *(*init)(struct nouveau_device *); - struct nouveau_screen *screen; + struct nouveau_screen *screen = NULL; int ret, dupfd = -1; pipe_mutex_lock(nouveau_screen_mutex); @@ -117,7 +117,7 @@ nouveau_drm_screen_create(int fd) } screen = init(dev); - if (!screen) + if (!screen || !screen->base.context_create) goto err; /* Use dupfd in hash table, to avoid errors if the original fd gets @@ -130,10 +130,14 @@ nouveau_drm_screen_create(int fd) return &screen->base; err: - if (dev) - nouveau_device_del(&dev); - else if (dupfd >= 0) - close(dupfd); + if (screen) { + screen->base.destroy(&screen->base); + } else { + if (dev) + nouveau_device_del(&dev); + else if (dupfd >= 0) + close(dupfd); + } pipe_mutex_unlock(nouveau_screen_mutex); return NULL; } |