From d9ef54923804d5fe44a1d3ad5c29e9b8e8382359 Mon Sep 17 00:00:00 2001
From: Marek Olšák <marek.olsak@amd.com>
Date: Fri, 20 Jan 2017 02:26:42 +0100
Subject: st/mesa: destroy pipe_context before destroying st_context (v2)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

If radeonsi starts compiling an optimized shader variant asynchronously
with a GL debug callback set and the application destroys the GL context,
radeonsi crashes when trying to write shader stats into the debug output
of a non-existent context after compilation, because st/mesa was destroyed
before pipe_context.

Firefox with WebGL2 enabled hits this bug.

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=99456

v2: protect against a double destroy in st_create_context_priv and callers.

Cc: 17.0 <mesa-stable@lists.freedesktop.org>
Reviewed-by: Nicolai Hähnle <nicolai.haehnle@amd.com>
---
 src/mesa/state_tracker/st_context.c | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

(limited to 'src/mesa/state_tracker')

diff --git a/src/mesa/state_tracker/st_context.c b/src/mesa/state_tracker/st_context.c
index 0eae971143b..55237345fc1 100644
--- a/src/mesa/state_tracker/st_context.c
+++ b/src/mesa/state_tracker/st_context.c
@@ -278,7 +278,7 @@ void st_invalidate_state(struct gl_context * ctx, GLbitfield new_state)
 
 
 static void
-st_destroy_context_priv(struct st_context *st)
+st_destroy_context_priv(struct st_context *st, bool destroy_pipe)
 {
    uint shader, i;
 
@@ -314,6 +314,10 @@ st_destroy_context_priv(struct st_context *st)
    st_invalidate_readpix_cache(st);
 
    cso_destroy_context(st->cso_context);
+
+   if (st->pipe && destroy_pipe)
+      st->pipe->destroy(st->pipe);
+
    free( st );
 }
 
@@ -503,7 +507,7 @@ st_create_context_priv( struct gl_context *ctx, struct pipe_context *pipe,
       /* This can happen when a core profile was requested, but the driver
        * does not support some features of GL 3.1 or later.
        */
-      st_destroy_context_priv(st);
+      st_destroy_context_priv(st, false);
       return NULL;
    }
 
@@ -579,7 +583,6 @@ destroy_tex_sampler_cb(GLuint id, void *data, void *userData)
  
 void st_destroy_context( struct st_context *st )
 {
-   struct pipe_context *pipe = st->pipe;
    struct gl_context *ctx = st->ctx;
    GLuint i;
 
@@ -608,11 +611,9 @@ void st_destroy_context( struct st_context *st )
 
    /* This will free the st_context too, so 'st' must not be accessed
     * afterwards. */
-   st_destroy_context_priv(st);
+   st_destroy_context_priv(st, true);
    st = NULL;
 
-   pipe->destroy( pipe );
-
    free(ctx);
 }
 
-- 
cgit v1.2.3