jerenkrantz 01/07/12 23:19:03
Modified: . configure.in
locks/unix crossproc.c
Log:
Implement POSIX pthread cross process locks that are "robust" - when the
process which owns the mutex dies, another process attempting to acquire
that lock will now receive EOWNERDIED instead of deadlocking. It is
then the responsibility of that holder of the mutex to restore it to a
consistent state.
This is lightly tested on Solaris 8/Intel 4/01. The mutex is recovered
(i.e. no deadlock), but this probably needs to be tested further. AFAIK,
Solaris 8 is the only platform which implements this.
Because the possiblity of the process dying while holding the lock is
too great, upgrade the conditions for using a pthread mutex for an
interprocess lock to require robust locks. This probably means that
Solaris (and maybe only Solaris 8) will use pthread_mutex_t for
cross-process locks. Too bad.
This completely avoids the question of why my httpd is segfaulting in the
first place, but now it doesn't deadlock when it does (to be fair, this is
with mod_mbox). BTW, the threaded MPM isn't starting up enough child
processes (only 1). StartServers is 3 - is the count of 3 supposed to
include the parent and the unixd child? If so, that's lame. If not,
we've got a bug somewhere in threaded MPM on Solaris 8. I'll have to
stare at my two whiteboards full of the diagrams of threaded MPM more.
Revision Changes Path
1.338 +34 -3 apr/configure.in
Index: configure.in
===================================================================
RCS file: /home/cvs/apr/configure.in,v
retrieving revision 1.337
retrieving revision 1.338
diff -u -r1.337 -r1.338
--- configure.in 2001/07/11 17:08:59 1.337
+++ configure.in 2001/07/13 06:18:56 1.338
@@ -985,15 +985,45 @@
exit(0);
}], [], [ac_cv_func_pthread_mutexattr_setpshared=no],
[ac_cv_func_pthread_mutexattr_setpshared=no]))
+ if test "$ac_cv_func_pthread_mutexattr_setpshared" = "yes"; then
+ AC_CHECK_FUNCS(pthread_mutexattr_setrobust_np)
+ if test "$ac_cv_func_pthread_mutexattr_setrobust_np" = "no"; then
+ AC_TRY_COMPILE([#define _POSIX_THREAD_PRIO_INHERIT
+ #include <sys/types.h>
+ #include <pthread.h>],[
+ int main()
+ {
+ pthread_mutex_t mutex;
+ pthread_mutexattr_t attr;
+ if (pthread_mutexattr_init(&attr))
+ exit(1);
+ if (pthread_mutexattr_setrobust_np(&attr,
+ PTHREAD_MUTEX_ROBUST_NP))
+ exit(2);
+ if (pthread_mutex_init(&mutex, &attr))
+ exit(3);
+ if (pthread_mutexattr_destroy(&attr))
+ exit(4);
+ if (pthread_mutex_destroy(&mutex))
+ exit(5);
+ exit(0);
+ }], [ac_cv_func_pthread_mutexattr_setrobust_np=yes], [])
+ if test "$ac_cv_func_pthread_mutexattr_setrobust_np" = "yes";
then
+ APR_ADDTO(CPPFLAGS, -D_POSIX_THREAD_PRIO_INHERIT)
+ fi
+ fi
+ fi
fi
# See which lock mechanisms we can support on this system.
-APR_IFALLYES(func:semget func:semctl define:SEM_UNDO, hassysvser="1",
hassysvser="0")
+APR_IFALLYES(func:semget func:semctl define:SEM_UNDO, hassysvser="1",
+ hassysvser="0")
APR_IFALLYES(func:flock define:LOCK_EX, hasflockser="1", hasflockser="0")
APR_IFALLYES(header:fcntl.h define:F_SETLK, hasfcntlser="1", hasfcntlser="0")
# note: the current APR use of shared mutex requires /dev/zero
APR_IFALLYES(header:pthread.h define:PTHREAD_PROCESS_SHARED dnl
- func:pthread_mutexattr_setpshared file:/dev/zero,
+ func:pthread_mutexattr_setpshared dnl
+ func:pthread_mutexattr_setrobust_np file:/dev/zero,
hasprocpthreadser="1", hasprocpthreadser="0")
APR_IFALLYES(struct:pthread_rw, hasrwlockser="1", hasrwlockser="0")
@@ -1008,7 +1038,8 @@
APR_DECIDE(USE_FCNTL_SERIALIZE, [SVR4-style fcntl()]))
# note: the current APR use of shared mutex requires /dev/zero
APR_IFALLYES(header:pthread.h define:PTHREAD_PROCESS_SHARED dnl
- func:pthread_mutexattr_setpshared file:/dev/zero,
+ func:pthread_mutexattr_setpshared dnl
+ func:pthread_mutexattr_setrobust_np file:/dev/zero,
APR_DECIDE(USE_PROC_PTHREAD_SERIALIZE, [pthread mutex]))
if test "x$apr_lock_method" != "x"; then
APR_DECISION_FORCE($apr_lock_method)
1.50 +30 -1 apr/locks/unix/crossproc.c
Index: crossproc.c
===================================================================
RCS file: /home/cvs/apr/locks/unix/crossproc.c,v
retrieving revision 1.49
retrieving revision 1.50
diff -u -r1.49 -r1.50
--- crossproc.c 2001/06/29 17:53:32 1.49
+++ crossproc.c 2001/07/13 06:19:01 1.50
@@ -225,6 +225,24 @@
return stat;
}
+#ifdef HAVE_PTHREAD_MUTEXATTR_SETROBUST_NP
+ if ((stat = pthread_mutexattr_setrobust_np(&mattr,
+ PTHREAD_MUTEX_ROBUST_NP))) {
+#ifdef PTHREAD_SETS_ERRNO
+ stat = errno;
+#endif
+ proc_pthread_cleanup(new);
+ return stat;
+ }
+ if ((stat = pthread_mutexattr_setprotocol(&mattr,
PTHREAD_PRIO_INHERIT))) {
+#ifdef PTHREAD_SETS_ERRNO
+ stat = errno;
+#endif
+ proc_pthread_cleanup(new);
+ return stat;
+ }
+#endif
+
if ((stat = pthread_mutex_init(new->pthread_interproc, &mattr))) {
#ifdef PTHREAD_SETS_ERRNO
stat = errno;
@@ -255,7 +273,16 @@
#ifdef PTHREAD_SETS_ERRNO
stat = errno;
#endif
+#ifdef HAVE_PTHREAD_MUTEXATTR_SETROBUST_NP
+ /* Okay, our owner died. Let's try to make it consistent again. */
+ if (stat == EOWNERDEAD) {
+ pthread_mutex_consistent_np(lock->pthread_interproc);
+ }
+ else
+ return stat;
+#else
return stat;
+#endif
}
lock->curr_locked = 1;
return APR_SUCCESS;
@@ -285,7 +312,9 @@
return stat;
}
-static apr_status_t proc_pthread_child_init(apr_lock_t **lock, apr_pool_t
*cont, const char *fname)
+static apr_status_t proc_pthread_child_init(apr_lock_t **lock,
+ apr_pool_t *cont,
+ const char *fname)
{
return APR_SUCCESS;
}