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: