Sophie

Sophie

distrib > Mageia > 7 > i586 > by-pkgid > b27ab7fc299bb0009420661d3e21deed > files > 6

ghostscript-9.27-1.3.mga7.src.rpm

From 1fb3a69df53754f6a000152606f52b2f4a658b97 Mon Sep 17 00:00:00 2001
From: Ray Johnston <ray.johnston@artifex.com>
Date: Wed, 3 Apr 2019 11:01:18 -0700
Subject: [PATCH] Fix crash reported by customer #531 with multi-threaded
 rendering.

This was a race condition where threads were continuing to be started
while we were tearing threads down. This doesn't occur with most usages
because we render the entire page, but with the customer's device, it
stops reading before the last line, but the multi-threading rendering
logic tried to keep starting threads (up to NumRenderingThreads) to
have later bands available.

The solution is to wait for all threads to be in the "THREAD_DONE"
state before freeing the threads.

Also, since the color_usage_array of the main thread is shared by the
rendering threads, wait until the threads are shut down before freeing
that.
---
 base/gxclist.c  | 2 +-
 base/gxclthrd.c | 9 +++++++--
 2 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/base/gxclist.c b/base/gxclist.c
index dff6b10..11512d1 100644
--- a/base/gxclist.c
+++ b/base/gxclist.c
@@ -769,9 +769,9 @@ clist_finish_page(gx_device *dev, bool flush)
     if (!CLIST_IS_WRITER((gx_device_clist *)dev)) {
         gx_device_clist_reader * const crdev =  &((gx_device_clist *)dev)->reader;
 
+        clist_teardown_render_threads(dev);
         gs_free_object(cdev->memory, crdev->color_usage_array, "clist_color_usage_array");
         crdev->color_usage_array = NULL;
-        clist_teardown_render_threads(dev);
 
        /* Free the icc table associated with this device.
            The threads that may have pointed to this were destroyed in
diff --git a/base/gxclthrd.c b/base/gxclthrd.c
index 7afd99a..eabcbf8 100644
--- a/base/gxclthrd.c
+++ b/base/gxclthrd.c
@@ -576,13 +576,18 @@ clist_teardown_render_threads(gx_device *dev)
     int i;
 
     if (crdev->render_threads != NULL) {
-        /* Wait for each thread to finish then free its memory */
+        /* Wait for all threads to finish */
         for (i = (crdev->num_render_threads - 1); i >= 0; i--) {
             clist_render_thread_control_t *thread = &(crdev->render_threads[i]);
-            gx_device_clist_common *thread_cdev = (gx_device_clist_common *)thread->cdev;
 
             if (thread->status == THREAD_BUSY)
                 gx_semaphore_wait(thread->sema_this);
+        }
+        /* then free each thread's memory */
+        for (i = (crdev->num_render_threads - 1); i >= 0; i--) {
+            clist_render_thread_control_t *thread = &(crdev->render_threads[i]);
+            gx_device_clist_common *thread_cdev = (gx_device_clist_common *)thread->cdev;
+
             /* Free control semaphores */
             gx_semaphore_free(thread->sema_group);
             gx_semaphore_free(thread->sema_this);
-- 
2.9.1