File fix-mutex-crash.patch of Package ghostscript-mini.4931
From 444e0bf9c43bae0261660e6318ba0e514c18d41e Mon Sep 17 00:00:00 2001
From: Chris Liddell <chris.liddell@artifex.com>
Date: Mon, 16 Mar 2015 12:52:49 +0000
Subject: [PATCH] Bug 695862: use PTHREAD_MUTEX_RECURSIVE(_NP) if available
or properly emulate recursive mutexes ourselves.
No cluster differences
---
config.mak.in | 2 +-
configure.ac | 37 +++++++++++++++++++----------
gs/Makefile.in | 2 +-
gs/base/gp_psync.c | 70 ++++++++++++++++++++++++++++++++++++++++++++----------
gs/configure.ac | 37 +++++++++++++++++++----------
5 files changed, 108 insertions(+), 40 deletions(-)
Index: ghostscript-9.15/configure.ac
===================================================================
--- ghostscript-9.15.orig/configure.ac
+++ ghostscript-9.15/configure.ac
@@ -494,8 +494,13 @@ AC_CHECK_LIB(m, cos)
SYNC="nosync"
PTHREAD_LIBS=""
+RECURSIVE_MUTEXATTR=""
-case `uname` in
+AC_ARG_ENABLE([threading], AC_HELP_STRING([--disable-threading],
+ [disable support for multithreaded rendering]))
+
+if test "$enable_threading" != "no"; then
+ case `uname` in
MINGW*)
AC_MSG_WARN([disabling support for pthreads......])
;;
@@ -504,11 +509,19 @@ case `uname` in
SYNC=posync;
PTHREAD_LIBS="-lpthread"
])
+ AC_TRY_COMPILE([#include <pthread.h>],
+ [static int k = PTHREAD_MUTEX_RECURSIVE;],
+ [RECURSIVE_MUTEXATTR="-DGS_RECURSIVE_MUTEXATTR=PTHREAD_MUTEX_RECURSIVE"],
+ [AC_TRY_COMPILE([#include <pthread.h>],
+ [static int k = PTHREAD_MUTEX_RECURSIVE_NP;],
+ [RECURSIVE_MUTEXATTR="-DGS_RECURSIVE_MUTEXATTR=PTHREAD_MUTEX_RECURSIVE_NP"])])
;;
-esac
+ esac
+fi
AC_SUBST(SYNC)
AC_SUBST(PTHREAD_LIBS)
+AC_SUBST(RECURSIVE_MUTEXATTR)
AC_MSG_CHECKING([for local trio library source])
if test -f $srcdir/trio/trio.h; then
Index: ghostscript-9.15/Makefile.in
===================================================================
--- ghostscript-9.15.orig/Makefile.in
+++ ghostscript-9.15/Makefile.in
@@ -142,7 +142,7 @@ GENOPT=
# -DHAVE_SSE2
# use sse2 intrinsics
-CAPOPT= @HAVE_MKSTEMP@ @HAVE_FILE64@ @HAVE_FSEEKO@ @HAVE_MKSTEMP64@ @HAVE_FONTCONFIG@ @HAVE_LIBIDN@ @HAVE_SETLOCALE@ @HAVE_SSE2@ @HAVE_DBUS@ @HAVE_BSWAP32@ @HAVE_BYTESWAP_H@ @HAVE_STRERROR@
+CAPOPT= @HAVE_MKSTEMP@ @HAVE_FILE64@ @HAVE_FSEEKO@ @HAVE_MKSTEMP64@ @HAVE_FONTCONFIG@ @HAVE_LIBIDN@ @HAVE_SETLOCALE@ @HAVE_SSE2@ @HAVE_DBUS@ @HAVE_BSWAP32@ @HAVE_BYTESWAP_H@ @HAVE_STRERROR@ @RECURSIVE_MUTEXATTR@
# Define the name of the executable file.
Index: ghostscript-9.15/base/gp_psync.c
===================================================================
--- ghostscript-9.15.orig/base/gp_psync.c
+++ ghostscript-9.15/base/gp_psync.c
@@ -128,13 +128,20 @@ gp_semaphore_signal(gp_semaphore * sema)
/* Monitor supports enter/leave semantics */
/*
- * We need PTHREAD_MUTEX_RECURSIVE behavior, but this isn't totally portable
- * so we implement it in a more portable fashion, keeping track of the
- * owner thread using 'pthread_self()'
+ * We need PTHREAD_MUTEX_RECURSIVE behavior, but this isn't
+ * supported on all pthread platforms, so if it's available
+ * we'll use it, otherwise we'll emulate it.
+ * GS_RECURSIVE_MUTEXATTR is set by the configure script
+ * on Unix-like machines to the attribute setting for
+ * PTHREAD_MUTEX_RECURSIVE - on linux this is usually
+ * PTHREAD_MUTEX_RECURSIVE_NP
*/
typedef struct gp_pthread_recursive_s {
pthread_mutex_t mutex; /* actual mutex */
+#ifndef GS_RECURSIVE_MUTEXATTR
pthread_t self_id; /* owner */
+ int lcount;
+#endif
} gp_pthread_recursive_t;
uint
@@ -148,12 +155,32 @@ gp_monitor_open(gp_monitor * mona)
{
pthread_mutex_t *mon;
int scode;
+ pthread_mutexattr_t attr;
+ pthread_mutexattr_t *attrp = NULL;
if (!mona)
return -1; /* monitors are not movable */
- mon = &((gp_pthread_recursive_t *)mona)->mutex;
+
+
+#ifdef GS_RECURSIVE_MUTEXATTR
+ attrp = &attr;
+ scode = pthread_mutexattr_init(attrp);
+ if (scode < 0) goto done;
+
+ scode = pthread_mutexattr_settype(attrp, GS_RECURSIVE_MUTEXATTR);
+ if (scode < 0) {
+ goto done;
+ }
+#else
((gp_pthread_recursive_t *)mona)->self_id = 0; /* Not valid unless mutex is locked */
- scode = pthread_mutex_init(mon, NULL);
+ ((gp_pthread_recursive_t *)mona)->lcount = 0;
+#endif
+
+ mon = &((gp_pthread_recursive_t *)mona)->mutex;
+ scode = pthread_mutex_init(mon, attrp);
+ if (attrp)
+ (void)pthread_mutexattr_destroy(attrp);
+done:
return SEM_ERROR_CODE(scode);
}
@@ -173,29 +200,48 @@ gp_monitor_enter(gp_monitor * mona)
pthread_mutex_t * const mon = (pthread_mutex_t *)mona;
int scode;
+#ifdef GS_RECURSIVE_MUTEXATTR
+ scode = pthread_mutex_lock(mon);
+#else
if ((scode = pthread_mutex_trylock(mon)) == 0) {
((gp_pthread_recursive_t *)mona)->self_id = pthread_self();
- return SEM_ERROR_CODE(scode);
+ ((gp_pthread_recursive_t *)mona)->lcount++;
} else {
- if (pthread_equal(pthread_self(),((gp_pthread_recursive_t *)mona)->self_id))
- return 0;
+ if (pthread_equal(pthread_self(),((gp_pthread_recursive_t *)mona)->self_id)) {
+ ((gp_pthread_recursive_t *)mona)->lcount++;
+ scode = 0;
+ }
else {
/* we were not the owner, wait */
scode = pthread_mutex_lock(mon);
((gp_pthread_recursive_t *)mona)->self_id = pthread_self();
- return SEM_ERROR_CODE(scode);
+ ((gp_pthread_recursive_t *)mona)->lcount++;
}
}
+#endif
+ return SEM_ERROR_CODE(scode);
}
int
gp_monitor_leave(gp_monitor * mona)
{
pthread_mutex_t * const mon = (pthread_mutex_t *)mona;
- int scode;
+ int scode = 0;
+#ifdef GS_RECURSIVE_MUTEXATTR
scode = pthread_mutex_unlock(mon);
- ((gp_pthread_recursive_t *)mona)->self_id = 0; /* Not valid unless mutex is locked */
+#else
+ if (pthread_equal(pthread_self(),((gp_pthread_recursive_t *)mona)->self_id)) {
+ if ((--((gp_pthread_recursive_t *)mona)->lcount) == 0) {
+ scode = pthread_mutex_unlock(mon);
+ ((gp_pthread_recursive_t *)mona)->self_id = 0; /* Not valid unless mutex is locked */
+
+ }
+ }
+ else {
+ scode = -1 /* should be EPERM */;
+ }
+#endif
return SEM_ERROR_CODE(scode);
}