[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#838328: ghostscript: need to backport fix for Ghostscript bug 695862 (segfault on certain machines)



Package: ghostscript
Version: 9.06~dfsg-2+deb8u1

Ghostscript <=9.15 has a bug which manifests itself only on certain
machines, causing it to segfault on certain PDF files.  This is due to
the incorrect assumption that unlocking an already unlocked mutex is a
no-op, something which is not guaranteed by Single Unix, and may or
may not be true depending on the hardware / kernel / phase of the
moon.  See <URL:
http://bugs.ghostscript.com/show_bug.cgi?id=695862
 > for details.

I have been bitten by this bug (changed my processor and suddenly all
sorts of PDF files wouldn't print), so it is not theoretical.

I believe Debian should backport some fix for this.  One possible fix
(tested on my machine) is attached: it consists of using
error-checking mutexes instead of fast ones (error-checking mutexes
are documented to return EPERM when unlocked twice).  This fix is
called "hacky" by Chris Liddell in the above-mentioned bug report
page, but I think it is perfectly sensible.  Otherwise, backport the
patch made to the ghostscript upstream itself.

-- 
     David A. Madore
   ( http://www.madore.org/~david/ )
Description: fix ghostscript bug #695862 by using error-checking mutexes
Author: David Madore <david+bugs@madore.org>
Last-Update: 2016-09-20

Index: ghostscript-9.06~dfsg/base/gp_psync.c
===================================================================
--- ghostscript-9.06~dfsg.orig/base/gp_psync.c
+++ ghostscript-9.06~dfsg/base/gp_psync.c
@@ -20,6 +20,7 @@
 #include <pthread.h>
 #include "gserrors.h"
 #include "gpsync.h"
+#include <errno.h>
 
 /*
  * Thanks to Larry Jones <larry.jones@sdrc.com> for this revision of
@@ -64,10 +65,21 @@ gp_semaphore_open(gp_semaphore * sema)
     pt_semaphore_t * const sem = (pt_semaphore_t *)sema;
     int scode;
 
+    /* Idiotic threads API won't let you create an error-checking mutex
+     * without creating another "mutexattr" object which itself
+     * has to be initialized.  This is _absurdly_ verbose! */
+    static pthread_mutexattr_t mutexattr;
+    static char mutexattr_initialized = 0;
+
     if (!sema)
         return -1;		/* semaphores are not movable */
+    if ( ! mutexattr_initialized ) {
+	mutexattr_initialized = 1;
+	pthread_mutexattr_init(&mutexattr);
+	pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_ERRORCHECK);
+    }
     sem->count = 0;
-    scode = pthread_mutex_init(&sem->mutex, NULL);
+    scode = pthread_mutex_init(&sem->mutex, &mutexattr);
     if (scode == 0)
         scode = pthread_cond_init(&sem->cond, NULL);
     return SEM_ERROR_CODE(scode);
@@ -103,6 +115,8 @@ gp_semaphore_wait(gp_semaphore * sema)
     if (scode == 0)
         --sem->count;
     scode2 = pthread_mutex_unlock(&sem->mutex);
+    if ( scode2 == EPERM )
+	scode2 = 0;
     if (scode == 0)
         scode = scode2;
     return SEM_ERROR_CODE(scode);
@@ -120,6 +134,8 @@ gp_semaphore_signal(gp_semaphore * sema)
     if (sem->count++ == 0)
         scode = pthread_cond_signal(&sem->cond);
     scode2 = pthread_mutex_unlock(&sem->mutex);
+    if ( scode2 == EPERM )
+	scode2 = 0;
     if (scode == 0)
         scode = scode2;
     return SEM_ERROR_CODE(scode);
@@ -149,11 +165,22 @@ gp_monitor_open(gp_monitor * mona)
     pthread_mutex_t *mon;
     int scode;
 
+    /* Idiotic threads API won't let you create an error-checking mutex
+     * without creating another "mutexattr" object which itself
+     * has to be initialized.  This is _absurdly_ verbose! */
+    static pthread_mutexattr_t mutexattr;
+    static char mutexattr_initialized = 0;
+
     if (!mona)
         return -1;		/* monitors are not movable */
+    if ( ! mutexattr_initialized ) {
+	mutexattr_initialized = 1;
+	pthread_mutexattr_init(&mutexattr);
+	pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_ERRORCHECK);
+    }
     mon = &((gp_pthread_recursive_t *)mona)->mutex;
     ((gp_pthread_recursive_t *)mona)->self_id = 0;	/* Not valid unless mutex is locked */
-    scode = pthread_mutex_init(mon, NULL);
+    scode = pthread_mutex_init(mon, &mutexattr);
     return SEM_ERROR_CODE(scode);
 }
 
@@ -195,6 +222,8 @@ gp_monitor_leave(gp_monitor * mona)
     int scode;
 
     scode = pthread_mutex_unlock(mon);
+    if ( scode == EPERM )
+	scode = 0;
     ((gp_pthread_recursive_t *)mona)->self_id = 0;	/* Not valid unless mutex is locked */
     return SEM_ERROR_CODE(scode);
 }

Reply to: