Here is a new patch regarding this, with the following changes wrt to
the previous one:

1. applies to latest trunk,
2. declares both POSIXSEM and PROC_PTHREAD as global in configure.in
(ie. they don't need a thread mutex when used as global mutex),
3. takes into account the new APR_LOCK_DEFAULT_TIMED from r1667900,
and return it in
apr_{proc,global}_mutex_mech()/apr_os_proc_mutex_get_ex() for
BeOS/OS2/Win32 (which have native timed mutexes),
4. gets rid of (unused) pthread_mutex_t *intraproc in apr_os_proc_mutex_t,
5. includes Netware changes (no more in a separate patch).

Still I could only test this on linux (where all unixes mechanisms are
available though), so review and (at least compile-)testing on other
patforms much appreciated.

Thanks,
Yann.


On Wed, Oct 1, 2014 at 4:24 PM, Yann Ylavic <[email protected]> wrote:
> Here are v2 of the previous patch(es) with the following addons :
>
> 1. Really address the showstopper from
> http://svn.apache.org/viewvc?view=revision&revision=1587066
>
> The previous patch only addressed the impossibility to specify the
> mechanism when set()ting an APR proc mutex from a OS proc mutex
> (disambiguation on unixes with multiple mechanisms using the fd
> available).
> This time the patch addresses the get() part of the issue, by introducing :
>
> APR_DECLARE(apr_status_t) apr_os_proc_mutex_get_ex(apr_os_proc_mutex_t
> *ospmutex,
>                                                    apr_proc_mutex_t *pmutex,
>                                                    apr_lockmech_e *mech);
>
> so that the caller can also get the mechanism used by the mutex.
>
> Again, like with apr_os_proc_mutex_set_ex(), I choose to not add the
> apr_lockmech_e to the apr_os_proc_mutex_t but instead use a new _ex()
> function. This allows to be compatible with the existing codes which
> would not have been aware of the new apr_os_proc_mutex_t field, with
> an uninitialized value for the mech that we could not have relied on.
>
> The new function is implemented on all platforms, and APR_LOCK_DEFAULT
> is used when only one mech is available.
>
> For unixes, the mech has been added to the
> apr_proc_mutex_unix_lock_methods_t struct (where the mech's name is
> already defined), so that it can be accessed immediatly with
> mutex->meth->mech (like mutex->meth->name).
>
>
> 2. Since apr_[global/proc]_mutex_name() are already available to get
> the name of the mech, I also added apr_[global/proc]_mutex_mech().
>
> Hence the caller can get the enum easily from the mutex (eg. without
> strcmp(apr_proc_mutex_name(mutex), "sysvsem") for every possible name
> like in httpd/os/unix/unixd.c).
>
>
> 3. Configure PROC_PTHREAD mutexes to be "global" (ie. they are also
> thread locking) in configure.in
>
> This matters for apr_global_mutex_t where APR_PROC_MUTEX_IS_GLOBAL is
> checked to determine whether an associated thread mutex is required to
> be thread-safe. When the (default) proc-mutex is "global", all the
> apr_global_mutex_* functions and types are #defined to the
> corresponding proc-mutex ones, otherwise apr_global_mutex_t is a
> struct containing both a proc and thread mutex, and the 2 locks are
> successively acquired/released upon apr_global_mutex_lock/unlock().
>
> This is not needed for proc-pthread mutexes, but since this is now the
> first (default) global proc-mutex mechanism on unixes, the case was
> not handled in include/arch/unix/apr_arch_global_mutex.h nor in
> locks/unix/global_mutex.c, and I had to use some #if
> !APR_PROC_MUTEX_IS_GLOBAL there to disable the global-mutex specific
> code.
>
> I also added a missing #define apr_global_mutex_perms_set
> apr_proc_mutex_perms_set when the proc-mutex is global.
>
>
> All the rest remain as decribed below (previous message).
>
> On Tue, Sep 30, 2014 at 10:35 PM, Yann Ylavic <[email protected]> wrote:
>>
>> the current apr_os_proc_mutex_get/set() implementation does
>> not do the right thing nor allow very much about posix semaphores wrt
>> these functions.
>>
>> The attached patch tries to address this by adding the native type
>> field (sem_t*) in apr_os_proc_mutex_t so that it can be got or put by
>> the caller explicitely (previously it was stored in a int/fd in the OS
>> type whereas the sem_t* was used only by the apr_proc_mutex_*()
>> functions).
>> This is abviously an ABI change since apr_os_proc_mutex_t is defined
>> in include/apr_portable.h, I don't think we can avoid this.
>>
>> Rather than also adding this new field to the unixes specific
>> apr_proc_mutex_t struct, I also modified the latter to replace all the
>> duplicated fields by a apr_os_proc_mutex_t member (called os). Since
>> apr_proc_mutex_t is private (include/arch/unix/apr_arch_proc_mutex.h
>> for unixes), this is not an API/ABI change.
>> This change implies the use of mutex->os.[native] instead of
>> mutex->[native] in the different mechanisms implementation, but it
>> also greatly simplifies apr_os_proc_mutex_get() to something as simple
>> as *osmutex = mutex->os.
>>
>> To help disambiguate the mechanism to be used when creating an
>> apr_proc_mutex_t from a native type, I also added the new
>> apr_os_proc_mutex_put_ex() function, which takes the lockmech as
>> parameter, and allows then for example to create a APR_LOCK_FLOCK
>> mutex from a fd when the default lockmech is SYSV (both using a fd as
>> native type).
>> This, I think, addresses the showstopper from
>> http://svn.apache.org/viewvc?view=revision&revision=1587066.
>> To initialize the apr_proc_mutex_t from the native type, I slightly
>> modified the existing/private proc_mutex_choose_method() function to
>> eventually take an os type as argument and do the right thing when not
>> NULL.
>> This function is of course also implemented in other platforms (where
>> APR_LOCK_DEFAULT is to be used as lockmech since there is the only
>> choice on non-unixes), so this is a another API addon (still in
>> include/apr_portable.h).
>>
>> On OS2, I have made apr_os_proc_mutex_get() return APR_SUCCESS since
>> the existing code looks correct (but the returned status), and
>> apr_os_proc_mutex_set() return APR_ENOPOOL when a NULL pool is given,
>> for consistency with other platforms.
>>
>> For consistency on all platforms still, in the unix code this time, I
>> changed the behaviour of the proc_mutex_*_cleanup() functions so that
>> they cleanup the native mutex even if the APR mutex was created by
>> apr_os_proc_mutex_set(), taking care of not closing the fd twice (for
>> proc mutexes using a fd, since the mutex is also mapped to an
>> apr_file_t).
>> This is however inconsistant with other APR types that can be created
>> from a native type (eg. apr_os_file_t using apr_os_file_put(), quite
>> logically since the object is not really owned by APR), so maybe I
>> should have done the opposite on non-unix platforms, let me know...
>>
>> Finally, netware, where the native mutex type is NXMutex_t (and not a
>> *pointer to* NXMutex_t).
>> AFAICT (from netware sources in nks/synch.h), the NXMutex_t struct is
>> defined as :
>>
>> typedef struct
>> {
>>    uint64_t  reserved1;
>>    void     *reserved2[10];
>> } NXMutex_t;
>>
>> This is hence impossible to get/set it via the
>> apr_os_proc_mutex_get/set() interface (would require a copy of the
>> struct, which is obviously not suitable).
>> The proposed change is to typedef NXMutex_t *apr_os_proc_mutex_t
>> instead (with the *pointer to*), and do the right thing in the get/set
>> functions.
>> That's another API/ABI change though, but I doubt anyone has already
>> used netware native mutex type successfully from/to
>> apr_proc_mutex_t...
>> Since I can't test it, this change is also attached here but in a
>> distinct patch, and it will probably require a review from someone who
>> knows netware and can test it (I don't, for both).
Index: configure.in
===================================================================
--- configure.in	(revision 1668004)
+++ configure.in	(working copy)
@@ -665,7 +665,6 @@ if test $force_generic_atomics = yes; then
              [Define if use of generic atomics is requested])
 fi
 
-AC_SUBST(proc_mutex_is_global)
 AC_SUBST(eolstr)
 AC_SUBST(INSTALL_SUBDIRS)
 
@@ -2219,12 +2218,15 @@ case $ac_decision in
         sysvser="1"
         ;;
     USE_POSIXSEM_SERIALIZE )
+        proc_mutex_is_global=1
         posixser="1"
         ;;
     USE_PROC_PTHREAD_SERIALIZE )
         procpthreadser="1"
+        proc_mutex_is_global=1
         ;;
     USE_BEOSSEM )
+        proc_mutex_is_global=1
         beossem="1"
         ;;
 esac
@@ -2308,6 +2310,8 @@ AC_SUBST(fcntlser)
 AC_SUBST(procpthreadser)
 AC_SUBST(pthreadser)
 
+AC_SUBST(proc_mutex_is_global)
+
 AC_MSG_CHECKING(if all interprocess locks affect threads)
 if test "x$apr_process_lock_is_global" = "xyes"; then
     proclockglobal="1"
Index: include/apr_global_mutex.h
===================================================================
--- include/apr_global_mutex.h	(revision 1668004)
+++ include/apr_global_mutex.h	(working copy)
@@ -141,11 +141,17 @@ APR_DECLARE(apr_status_t) apr_global_mutex_destroy
 APR_DECLARE(const char *) apr_global_mutex_lockfile(apr_global_mutex_t *mutex);
 
 /**
- * Display the name of the mutex, as it relates to the actual method used
- * for the underlying apr_proc_mutex_t, if any.  NULL is returned if
- * there is no underlying apr_proc_mutex_t.
- * @param mutex the name of the mutex
+ * Get the mechanism of the mutex, as it relates to the actual method
+ * used for the underlying apr_proc_mutex_t.
+ * @param mutex the mutex to get the mechanism from.
  */
+APR_DECLARE(apr_lockmech_e) apr_global_mutex_mech(apr_global_mutex_t *mutex);
+
+/**
+ * Get the mechanism's name of the mutex, as it relates to the actual method
+ * used for the underlying apr_proc_mutex_t.
+ * @param mutex the mutex to get the mechanism's name from.
+ */
 APR_DECLARE(const char *) apr_global_mutex_name(apr_global_mutex_t *mutex);
 
 /**
@@ -174,7 +180,9 @@ APR_POOL_DECLARE_ACCESSOR(global_mutex);
 #define apr_global_mutex_unlock     apr_proc_mutex_unlock
 #define apr_global_mutex_destroy    apr_proc_mutex_destroy
 #define apr_global_mutex_lockfile   apr_proc_mutex_lockfile
+#define apr_global_mutex_mech       apr_proc_mutex_mech
 #define apr_global_mutex_name       apr_proc_mutex_name
+#define apr_global_mutex_perms_set  apr_proc_mutex_perms_set
 #define apr_global_mutex_pool_get   apr_proc_mutex_pool_get
 
 #endif
Index: include/apr_portable.h
===================================================================
--- include/apr_portable.h	(revision 1668004)
+++ include/apr_portable.h	(working copy)
@@ -46,6 +46,9 @@
 #if APR_HAVE_PTHREAD_H
 #include <pthread.h>
 #endif
+#if APR_HAVE_SEMAPHORE_H
+#include <semaphore.h>
+#endif
 
 #ifdef __cplusplus
 extern "C" {
@@ -109,7 +112,7 @@ typedef void*                 apr_os_shm_t;
 typedef int                   apr_os_file_t;
 typedef DIR                   apr_os_dir_t;
 typedef int                   apr_os_sock_t;
-typedef NXMutex_t             apr_os_proc_mutex_t;
+typedef NXMutex_t *           apr_os_proc_mutex_t;
 typedef NXThreadId_t          apr_os_thread_t;
 typedef long                  apr_os_proc_t;
 typedef NXKey_t               apr_os_threadkey_t; 
@@ -133,13 +136,10 @@ struct apr_os_proc_mutex_t {
     /** Value used for PTHREAD serialization */
     pthread_mutex_t *pthread_interproc;
 #endif
-#if APR_HAS_THREADS
-    /* If no threads, no need for thread locks */
-#if APR_USE_PTHREAD_SERIALIZE
-    /** This value is currently unused within APR and Apache */ 
-    pthread_mutex_t *intraproc;
+#if APR_HAS_POSIXSEM_SERIALIZE
+    /** Value used for POSIX semaphores serialization */
+    sem_t *psem_interproc;
 #endif
-#endif
 };
 
 typedef int                   apr_os_file_t;        /**< native file */
@@ -241,7 +241,7 @@ APR_DECLARE(apr_status_t) apr_os_sock_get(apr_os_s
                                           apr_socket_t *sock);
 
 /**
- * Convert the proc mutex from os specific type to apr type
+ * Convert the proc mutex from apr type to os specific type
  * @param ospmutex The os specific proc mutex we are converting to.
  * @param pmutex The apr proc mutex to convert.
  */
@@ -249,6 +249,19 @@ APR_DECLARE(apr_status_t) apr_os_proc_mutex_get(ap
                                                 apr_proc_mutex_t *pmutex);
 
 /**
+ * Convert the proc mutex from apr type to os specific type, also
+ * providing the mechanism used by the apr mutex.
+ * @param ospmutex The os specific proc mutex we are converting to.
+ * @param pmutex The apr proc mutex to convert.
+ * @param mech The mechanism used by the apr proc mutex (if not NULL).
+ * @remark Allows for disambiguation for platforms with multiple mechanisms
+ *         available.
+ */
+APR_DECLARE(apr_status_t) apr_os_proc_mutex_get_ex(apr_os_proc_mutex_t *ospmutex, 
+                                                   apr_proc_mutex_t *pmutex,
+                                                   apr_lockmech_e *mech);
+
+/**
  * Get the exploded time in the platforms native format.
  * @param ostime the native time format
  * @param aprtime the time to convert
@@ -416,6 +429,21 @@ APR_DECLARE(apr_status_t) apr_os_proc_mutex_put(ap
                                                 apr_pool_t *cont); 
 
 /**
+ * Convert the proc mutex from os specific type to apr type, using the
+ * specified mechanism.
+ * @param pmutex The apr proc mutex we are converting to.
+ * @param ospmutex The os specific proc mutex to convert.
+ * @param mech The apr mutex locking mechanism
+ * @param cont The pool to use if it is needed.
+ * @remark Allows for disambiguation for platforms with multiple mechanisms
+ *         available.
+ */
+APR_DECLARE(apr_status_t) apr_os_proc_mutex_put_ex(apr_proc_mutex_t **pmutex,
+                                                apr_os_proc_mutex_t *ospmutex,
+                                                apr_lockmech_e mech,
+                                                apr_pool_t *cont); 
+
+/**
  * Put the imploded time in the APR format.
  * @param aprtime the APR time format
  * @param ostime the time to convert
Index: include/apr_proc_mutex.h
===================================================================
--- include/apr_proc_mutex.h	(revision 1668004)
+++ include/apr_proc_mutex.h	(working copy)
@@ -154,10 +154,17 @@ APR_DECLARE(apr_status_t) apr_proc_mutex_cleanup(v
 APR_DECLARE(const char *) apr_proc_mutex_lockfile(apr_proc_mutex_t *mutex);
 
 /**
- * Display the name of the mutex, as it relates to the actual method used.
- * This matches the valid options for Apache's AcceptMutex directive
- * @param mutex the name of the mutex
+ * Get the mechanism of the mutex, as it relates to the actual method
+ * used for the underlying apr_proc_mutex_t.
+ * @param mutex the mutex to get the mechanism from.
  */
+APR_DECLARE(apr_lockmech_e) apr_proc_mutex_mech(apr_proc_mutex_t *mutex);
+
+/**
+ * Get the mechanism's name of the mutex, as it relates to the actual method
+ * used for the underlying apr_proc_mutex_t.
+ * @param mutex the mutex to get the mechanism's name from.
+ */
 APR_DECLARE(const char *) apr_proc_mutex_name(apr_proc_mutex_t *mutex);
 
 /**
Index: include/arch/unix/apr_arch_global_mutex.h
===================================================================
--- include/arch/unix/apr_arch_global_mutex.h	(revision 1668004)
+++ include/arch/unix/apr_arch_global_mutex.h	(working copy)
@@ -18,11 +18,14 @@
 #define GLOBAL_MUTEX_H
 
 #include "apr.h"
+#include "apr_global_mutex.h"
+#include "apr_arch_proc_mutex.h"
+
+#if !APR_PROC_MUTEX_IS_GLOBAL
+
 #include "apr_private.h"
 #include "apr_general.h"
 #include "apr_lib.h"
-#include "apr_global_mutex.h"
-#include "apr_arch_proc_mutex.h"
 #include "apr_arch_thread_mutex.h"
 
 struct apr_global_mutex_t {
@@ -33,5 +36,7 @@ struct apr_global_mutex_t {
 #endif /* APR_HAS_THREADS */
 };
 
+#endif /* !APR_PROC_MUTEX_IS_GLOBAL */
+
 #endif  /* GLOBAL_MUTEX_H */
 
Index: include/arch/unix/apr_arch_proc_mutex.h
===================================================================
--- include/arch/unix/apr_arch_proc_mutex.h	(revision 1668004)
+++ include/arch/unix/apr_arch_proc_mutex.h	(working copy)
@@ -63,9 +63,6 @@
 #if APR_HAVE_PTHREAD_H
 #include <pthread.h>
 #endif
-#if APR_HAVE_SEMAPHORE_H
-#include <semaphore.h>
-#endif
 /* End System Headers */
 
 struct apr_proc_mutex_unix_lock_methods_t {
@@ -78,6 +75,7 @@ struct apr_proc_mutex_unix_lock_methods_t {
     apr_status_t (*cleanup)(void *);
     apr_status_t (*child_init)(apr_proc_mutex_t **, apr_pool_t *, const char *);
     apr_status_t (*perms_set)(apr_proc_mutex_t *, apr_fileperms_t, apr_uid_t, apr_gid_t);
+    apr_lockmech_e mech;
     const char *name;
 };
 typedef struct apr_proc_mutex_unix_lock_methods_t apr_proc_mutex_unix_lock_methods_t;
@@ -96,18 +94,13 @@ union semun {
 struct apr_proc_mutex_t {
     apr_pool_t *pool;
     const apr_proc_mutex_unix_lock_methods_t *meth;
-    const apr_proc_mutex_unix_lock_methods_t *inter_meth;
     int curr_locked;
     char *fname;
-#if APR_HAS_SYSVSEM_SERIALIZE || APR_HAS_FCNTL_SERIALIZE || APR_HAS_FLOCK_SERIALIZE
+    apr_os_proc_mutex_t os;
+#if APR_HAS_FCNTL_SERIALIZE || APR_HAS_FLOCK_SERIALIZE
     apr_file_t *interproc;
+    int closed_by_interproc;
 #endif
-#if APR_HAS_POSIXSEM_SERIALIZE
-    sem_t *psem_interproc;
-#endif
-#if APR_HAS_PROC_PTHREAD_SERIALIZE
-    pthread_mutex_t *pthread_interproc;
-#endif
 };
 
 void apr_proc_mutex_unix_setup_lock(void);
Index: locks/beos/proc_mutex.c
===================================================================
--- locks/beos/proc_mutex.c	(revision 1668004)
+++ locks/beos/proc_mutex.c	(working copy)
@@ -182,6 +182,11 @@ APR_DECLARE(const char *) apr_proc_mutex_lockfile(
     return NULL;
 }
 
+APR_DECLARE(apr_lockmech_e) apr_proc_mutex_mech(apr_proc_mutex_t *mutex)
+{
+    return APR_LOCK_DEFAULT_TIMED;
+}
+
 APR_DECLARE(const char *) apr_proc_mutex_name(apr_proc_mutex_t *mutex)
 {
     return "beossem";
@@ -198,21 +203,35 @@ APR_POOL_IMPLEMENT_ACCESSOR(proc_mutex)
 
 /* Implement OS-specific accessors defined in apr_portable.h */
 
-APR_DECLARE(apr_status_t) apr_os_proc_mutex_get(apr_os_proc_mutex_t *ospmutex,
-                                                apr_proc_mutex_t *pmutex)
+APR_DECLARE(apr_status_t) apr_os_proc_mutex_get_ex(apr_os_proc_mutex_t *ospmutex, 
+                                                   apr_proc_mutex_t *pmutex,
+                                                   apr_lockmech_e *mech)
 {
     ospmutex->sem = pmutex->Lock;
     ospmutex->ben = pmutex->LockCount;
+    if (mech) {
+        *mech = APR_LOCK_DEFAULT_TIMED;
+    }
     return APR_SUCCESS;
 }
 
-APR_DECLARE(apr_status_t) apr_os_proc_mutex_put(apr_proc_mutex_t **pmutex,
+APR_DECLARE(apr_status_t) apr_os_proc_mutex_get(apr_os_proc_mutex_t *ospmutex,
+                                                apr_proc_mutex_t *pmutex)
+{
+    return apr_os_proc_mutex_get_ex(ospmutex, pmutex, NULL);
+}
+
+APR_DECLARE(apr_status_t) apr_os_proc_mutex_put_ex(apr_proc_mutex_t **pmutex,
                                                 apr_os_proc_mutex_t *ospmutex,
+                                                apr_lockmech_e mech,
                                                 apr_pool_t *pool)
 {
     if (pool == NULL) {
         return APR_ENOPOOL;
     }
+    if (mech != APR_LOCK_DEFAULT && mech != APR_LOCK_DEFAULT_TIMED) {
+        return APR_ENOTIMPL;
+    }
     if ((*pmutex) == NULL) {
         (*pmutex) = (apr_proc_mutex_t *)apr_pcalloc(pool, sizeof(apr_proc_mutex_t));
         (*pmutex)->pool = pool;
@@ -222,3 +241,10 @@ APR_POOL_IMPLEMENT_ACCESSOR(proc_mutex)
     return APR_SUCCESS;
 }
 
+APR_DECLARE(apr_status_t) apr_os_proc_mutex_put(apr_proc_mutex_t **pmutex,
+                                                apr_os_proc_mutex_t *ospmutex,
+                                                apr_pool_t *pool)
+{
+    return apr_os_proc_mutex_put_ex(pmutex, ospmutex, APR_LOCK_DEFAULT_TIMED, pool);
+}
+
Index: locks/netware/proc_mutex.c
===================================================================
--- locks/netware/proc_mutex.c	(revision 1668004)
+++ locks/netware/proc_mutex.c	(working copy)
@@ -105,6 +105,11 @@ APR_DECLARE(const char *) apr_proc_mutex_lockfile(
     return NULL;
 }
 
+APR_DECLARE(apr_lockmech_e) apr_proc_mutex_mech(apr_proc_mutex_t *mutex)
+{
+    return APR_LOCK_DEFAULT;
+}
+
 APR_DECLARE(const char *) apr_proc_mutex_name(apr_proc_mutex_t *mutex)
 {
     return "netwarethread";
@@ -121,18 +126,51 @@ APR_POOL_IMPLEMENT_ACCESSOR(proc_mutex)
 
 /* Implement OS-specific accessors defined in apr_portable.h */
 
-apr_status_t apr_os_proc_mutex_get(apr_os_proc_mutex_t *ospmutex,
-                                   apr_proc_mutex_t *pmutex)
+APR_DECLARE(apr_status_t) apr_os_proc_mutex_get_ex(apr_os_proc_mutex_t *ospmutex, 
+                                                   apr_proc_mutex_t *pmutex,
+                                                   apr_lockmech_e *mech)
 {
-    if (pmutex)
-        ospmutex = pmutex->mutex->mutex;
-    return APR_ENOLOCK;
+    if (!pmutex->mutex) {
+        return APR_ENOLOCK;
+    }
+    *ospmutex = pmutex->mutex->mutex;
+    if (mech) {
+        *mech = APR_LOCK_DEFAULT;
+    }
+    return APR_SUCCESS;
 }
 
-apr_status_t apr_os_proc_mutex_put(apr_proc_mutex_t **pmutex,
-                                   apr_os_proc_mutex_t *ospmutex,
-                                   apr_pool_t *pool)
+APR_DECLARE(apr_status_t) apr_os_proc_mutex_get(apr_os_proc_mutex_t *ospmutex,
+                                                apr_proc_mutex_t *pmutex)
 {
-    return APR_ENOTIMPL;
+    return apr_os_proc_mutex_get_ex(ospmutex, pmutex, NULL);
 }
 
+APR_DECLARE(apr_status_t) apr_os_proc_mutex_put_ex(apr_proc_mutex_t **pmutex,
+                                                apr_os_proc_mutex_t *ospmutex,
+                                                apr_lockmech_e mech,
+                                                apr_pool_t *pool)
+{
+    if (pool == NULL) {
+        return APR_ENOPOOL;
+    }
+    if (mech != APR_LOCK_DEFAULT) {
+        return APR_ENOTIMPL;
+    }
+    if ((*pmutex) == NULL) {
+        (*pmutex) = apr_pcalloc(pool, sizeof(apr_proc_mutex_t));
+        (*pmutex)->pool = pool;
+    }
+    (*pmutex)->mutex = apr_pcalloc(pool, sizeof(apr_thread_mutex_t));
+    (*pmutex)->mutex->mutex = *ospmutex;
+    (*pmutex)->mutex->pool = pool;
+    return APR_SUCCESS;
+}
+
+APR_DECLARE(apr_status_t) apr_os_proc_mutex_put(apr_proc_mutex_t **pmutex,
+                                                apr_os_proc_mutex_t *ospmutex,
+                                                apr_pool_t *pool)
+{
+    return apr_os_proc_mutex_put_ex(pmutex, ospmutex, APR_LOCK_DEFAULT, pool);
+}
+
Index: locks/os2/proc_mutex.c
===================================================================
--- locks/os2/proc_mutex.c	(revision 1668004)
+++ locks/os2/proc_mutex.c	(working copy)
@@ -60,6 +60,11 @@ APR_DECLARE(const char *) apr_proc_mutex_lockfile(
     return NULL;
 }
 
+APR_DECLARE(apr_lockmech_e) apr_proc_mutex_mech(apr_proc_mutex_t *mutex)
+{
+    return APR_LOCK_DEFAULT_TIMED;
+}
+
 APR_DECLARE(const char *) apr_proc_mutex_name(apr_proc_mutex_t *mutex)
 {
     return "os2sem";
@@ -243,20 +248,35 @@ APR_POOL_IMPLEMENT_ACCESSOR(proc_mutex)
 
 /* Implement OS-specific accessors defined in apr_portable.h */
 
+APR_DECLARE(apr_status_t) apr_os_proc_mutex_get_ex(apr_os_proc_mutex_t *ospmutex, 
+                                                   apr_proc_mutex_t *pmutex,
+                                                   apr_lockmech_e *mech)
+{
+    *ospmutex = pmutex->hMutex;
+    if (mech) {
+        *mech = APR_LOCK_DEFAULT_TIMED;
+    }
+    return APR_SUCCESS;
+}
+
 APR_DECLARE(apr_status_t) apr_os_proc_mutex_get(apr_os_proc_mutex_t *ospmutex,
                                                 apr_proc_mutex_t *pmutex)
 {
-    *ospmutex = pmutex->hMutex;
-    return APR_ENOTIMPL;
+    return apr_os_proc_mutex_get_ex(ospmutex, pmutex, NULL);
 }
 
-
-
-APR_DECLARE(apr_status_t) apr_os_proc_mutex_put(apr_proc_mutex_t **pmutex,
+APR_DECLARE(apr_status_t) apr_os_proc_mutex_put_ex(apr_proc_mutex_t **pmutex,
                                                 apr_os_proc_mutex_t *ospmutex,
+                                                apr_lockmech_e mech,
                                                 apr_pool_t *pool)
 {
     apr_proc_mutex_t *new;
+    if (pool == NULL) {
+        return APR_ENOPOOL;
+    }
+    if (mech != APR_LOCK_DEFAULT && mech != APR_LOCK_DEFAULT_TIMED) {
+        return APR_ENOTIMPL;
+    }
 
     new = (apr_proc_mutex_t *)apr_palloc(pool, sizeof(apr_proc_mutex_t));
     new->pool       = pool;
@@ -268,3 +288,10 @@ APR_DECLARE(apr_status_t) apr_os_proc_mutex_get(ap
     return APR_SUCCESS;
 }
 
+APR_DECLARE(apr_status_t) apr_os_proc_mutex_put(apr_proc_mutex_t **pmutex,
+                                                apr_os_proc_mutex_t *ospmutex,
+                                                apr_pool_t *pool)
+{
+    return apr_os_proc_mutex_put_ex(pmutex, ospmutex, APR_LOCK_DEFAULT_TIMED, pool);
+}
+
Index: locks/unix/global_mutex.c
===================================================================
--- locks/unix/global_mutex.c	(revision 1668004)
+++ locks/unix/global_mutex.c	(working copy)
@@ -15,6 +15,9 @@
  */
 
 #include "apr.h"
+
+#if !APR_PROC_MUTEX_IS_GLOBAL
+
 #include "apr_strings.h"
 #include "apr_arch_global_mutex.h"
 #include "apr_proc_mutex.h"
@@ -59,7 +62,7 @@ APR_DECLARE(apr_status_t) apr_global_mutex_create(
     }
 
 #if APR_HAS_THREADS
-    if (m->proc_mutex->inter_meth->flags & APR_PROCESS_LOCK_MECH_IS_GLOBAL) {
+    if (m->proc_mutex->meth->flags & APR_PROCESS_LOCK_MECH_IS_GLOBAL) {
         m->thread_mutex = NULL; /* We don't need a thread lock. */
     }
     else {
@@ -212,6 +215,11 @@ APR_DECLARE(const char *) apr_global_mutex_lockfil
     return apr_proc_mutex_lockfile(mutex->proc_mutex);
 }
 
+APR_DECLARE(apr_lockmech_e) apr_global_mutex_mech(apr_proc_mutex_t *mutex)
+{
+    return apr_proc_mutex_mech(mutex->proc_mutex);
+}
+
 APR_DECLARE(const char *) apr_global_mutex_name(apr_global_mutex_t *mutex)
 {
     return apr_proc_mutex_name(mutex->proc_mutex);
@@ -227,3 +235,6 @@ APR_PERMS_SET_IMPLEMENT(global_mutex)
 }
 
 APR_POOL_IMPLEMENT_ACCESSOR(global_mutex)
+
+#endif /* !APR_PROC_MUTEX_IS_GLOBAL */
+
Index: locks/unix/proc_mutex.c
===================================================================
--- locks/unix/proc_mutex.c	(revision 1668004)
+++ locks/unix/proc_mutex.c	(working copy)
@@ -56,7 +56,7 @@ static apr_status_t proc_mutex_posix_cleanup(void
 {
     apr_proc_mutex_t *mutex = mutex_;
     
-    if (sem_close(mutex->psem_interproc) < 0) {
+    if (sem_close(mutex->os.psem_interproc) < 0) {
         return errno;
     }
 
@@ -71,8 +71,6 @@ static apr_status_t proc_mutex_posix_create(apr_pr
     sem_t *psem;
     char semname[APR_MD5_DIGESTSIZE * 2 + 2];
     
-    new_mutex->interproc = apr_palloc(new_mutex->pool,
-                                      sizeof(*new_mutex->interproc));
     /*
      * This bogusness is to follow what appears to be the
      * lowest common denominator in Posix semaphore naming:
@@ -135,7 +133,7 @@ static apr_status_t proc_mutex_posix_create(apr_pr
     }
     /* Ahhh. The joys of Posix sems. Predelete it... */
     sem_unlink(semname);
-    new_mutex->psem_interproc = psem;
+    new_mutex->os.psem_interproc = psem;
     new_mutex->fname = apr_pstrdup(new_mutex->pool, semname);
     apr_pool_cleanup_register(new_mutex->pool, (void *)new_mutex,
                               apr_proc_mutex_cleanup, 
@@ -148,7 +146,7 @@ static apr_status_t proc_mutex_posix_acquire(apr_p
     int rc;
 
     do {
-        rc = sem_wait(mutex->psem_interproc);
+        rc = sem_wait(mutex->os.psem_interproc);
     } while (rc < 0 && errno == EINTR);
     if (rc < 0) {
         return errno;
@@ -162,7 +160,7 @@ static apr_status_t proc_mutex_posix_tryacquire(ap
     int rc;
 
     do {
-        rc = sem_trywait(mutex->psem_interproc);
+        rc = sem_trywait(mutex->os.psem_interproc);
     } while (rc < 0 && errno == EINTR);
     if (rc < 0) {
         if (errno == EAGAIN) {
@@ -193,7 +191,7 @@ static apr_status_t proc_mutex_posix_timedacquire(
         abstime.tv_nsec = apr_time_usec(timeout) * 1000; /* nanoseconds */
         
         do {
-            rc = sem_timedwait(mutex->psem_interproc, &abstime);
+            rc = sem_timedwait(mutex->os.psem_interproc, &abstime);
         } while (rc < 0 && errno == EINTR);
         if (rc < 0) {
             if (errno == ETIMEDOUT) {
@@ -212,7 +210,7 @@ static apr_status_t proc_mutex_posix_timedacquire(
 static apr_status_t proc_mutex_posix_release(apr_proc_mutex_t *mutex)
 {
     mutex->curr_locked = 0;
-    if (sem_post(mutex->psem_interproc) < 0) {
+    if (sem_post(mutex->os.psem_interproc) < 0) {
         /* any failure is probably fatal, so no big deal to leave
          * ->curr_locked at 0. */
         return errno;
@@ -235,6 +233,7 @@ static const apr_proc_mutex_unix_lock_methods_t mu
     proc_mutex_posix_cleanup,
     proc_mutex_no_child_init,
     proc_mutex_no_perms_set,
+    APR_LOCK_POSIXSEM,
     "posixsem"
 };
 
@@ -264,9 +263,9 @@ static apr_status_t proc_mutex_sysv_cleanup(void *
     apr_proc_mutex_t *mutex=mutex_;
     union semun ick;
     
-    if (mutex->interproc->filedes != -1) {
+    if (mutex->os.crossproc != -1) {
         ick.val = 0;
-        semctl(mutex->interproc->filedes, 0, IPC_RMID, ick);
+        semctl(mutex->os.crossproc, 0, IPC_RMID, ick);
     }
     return APR_SUCCESS;
 }    
@@ -277,18 +276,17 @@ static apr_status_t proc_mutex_sysv_create(apr_pro
     union semun ick;
     apr_status_t rv;
     
-    new_mutex->interproc = apr_palloc(new_mutex->pool, sizeof(*new_mutex->interproc));
-    new_mutex->interproc->filedes = semget(IPC_PRIVATE, 1, IPC_CREAT | 0600);
-
-    if (new_mutex->interproc->filedes < 0) {
+    new_mutex->os.crossproc = semget(IPC_PRIVATE, 1, IPC_CREAT | 0600);
+    if (new_mutex->os.crossproc == -1) {
         rv = errno;
         proc_mutex_sysv_cleanup(new_mutex);
         return rv;
     }
     ick.val = 1;
-    if (semctl(new_mutex->interproc->filedes, 0, SETVAL, ick) < 0) {
+    if (semctl(new_mutex->os.crossproc, 0, SETVAL, ick) < 0) {
         rv = errno;
         proc_mutex_sysv_cleanup(new_mutex);
+        new_mutex->os.crossproc = -1;
         return rv;
     }
     new_mutex->curr_locked = 0;
@@ -303,7 +301,7 @@ static apr_status_t proc_mutex_sysv_acquire(apr_pr
     int rc;
 
     do {
-        rc = semop(mutex->interproc->filedes, &proc_mutex_op_on, 1);
+        rc = semop(mutex->os.crossproc, &proc_mutex_op_on, 1);
     } while (rc < 0 && errno == EINTR);
     if (rc < 0) {
         return errno;
@@ -317,7 +315,7 @@ static apr_status_t proc_mutex_sysv_tryacquire(apr
     int rc;
 
     do {
-        rc = semop(mutex->interproc->filedes, &proc_mutex_op_try, 1);
+        rc = semop(mutex->os.crossproc, &proc_mutex_op_try, 1);
     } while (rc < 0 && errno == EINTR);
     if (rc < 0) {
         if (errno == EAGAIN) {
@@ -369,7 +367,7 @@ static apr_status_t proc_mutex_sysv_release(apr_pr
 
     mutex->curr_locked = 0;
     do {
-        rc = semop(mutex->interproc->filedes, &proc_mutex_op_off, 1);
+        rc = semop(mutex->os.crossproc, &proc_mutex_op_off, 1);
     } while (rc < 0 && errno == EINTR);
     if (rc < 0) {
         return errno;
@@ -389,7 +387,7 @@ static apr_status_t proc_mutex_sysv_perms_set(apr_
     buf.sem_perm.gid = gid;
     buf.sem_perm.mode = apr_unix_perms2mode(perms);
     ick.buf = &buf;
-    if (semctl(mutex->interproc->filedes, 0, IPC_SET, ick) < 0) {
+    if (semctl(mutex->os.crossproc, 0, IPC_SET, ick) < 0) {
         return errno;
     }
     return APR_SUCCESS;
@@ -410,6 +408,7 @@ static const apr_proc_mutex_unix_lock_methods_t mu
     proc_mutex_sysv_cleanup,
     proc_mutex_no_child_init,
     proc_mutex_sysv_perms_set,
+    APR_LOCK_SYSVSEM,
     "sysvsem"
 };
 
@@ -423,7 +422,7 @@ static apr_status_t proc_mutex_proc_pthread_cleanu
     apr_status_t rv;
 
     if (mutex->curr_locked == 1) {
-        if ((rv = pthread_mutex_unlock(mutex->pthread_interproc))) {
+        if ((rv = pthread_mutex_unlock(mutex->os.pthread_interproc))) {
 #ifdef HAVE_ZOS_PTHREADS
             rv = errno;
 #endif
@@ -432,7 +431,7 @@ static apr_status_t proc_mutex_proc_pthread_cleanu
     }
     /* curr_locked is set to -1 until the mutex has been created */
     if (mutex->curr_locked != -1) {
-        if ((rv = pthread_mutex_destroy(mutex->pthread_interproc))) {
+        if ((rv = pthread_mutex_destroy(mutex->os.pthread_interproc))) {
 #ifdef HAVE_ZOS_PTHREADS
             rv = errno;
 #endif
@@ -439,7 +438,7 @@ static apr_status_t proc_mutex_proc_pthread_cleanu
             return rv;
         }
     }
-    if (munmap((caddr_t)mutex->pthread_interproc, sizeof(pthread_mutex_t))) {
+    if (munmap((caddr_t)mutex->os.pthread_interproc, sizeof(pthread_mutex_t))) {
         return errno;
     }
     return APR_SUCCESS;
@@ -457,12 +456,12 @@ static apr_status_t proc_mutex_proc_pthread_create
         return errno;
     }
 
-    new_mutex->pthread_interproc = (pthread_mutex_t *)mmap(
-                                       (caddr_t) 0, 
-                                       sizeof(pthread_mutex_t), 
-                                       PROT_READ | PROT_WRITE, MAP_SHARED,
-                                       fd, 0); 
-    if (new_mutex->pthread_interproc == (pthread_mutex_t *) (caddr_t) -1) {
+    new_mutex->os.pthread_interproc = (pthread_mutex_t *)mmap(
+                                           (caddr_t) 0, 
+                                           sizeof(pthread_mutex_t), 
+                                           PROT_READ | PROT_WRITE, MAP_SHARED,
+                                           fd, 0); 
+    if (new_mutex->os.pthread_interproc == (pthread_mutex_t *) (caddr_t) -1) {
         close(fd);
         return errno;
     }
@@ -506,7 +505,7 @@ static apr_status_t proc_mutex_proc_pthread_create
     }
 #endif /* HAVE_PTHREAD_MUTEX_ROBUST */
 
-    if ((rv = pthread_mutex_init(new_mutex->pthread_interproc, &mattr))) {
+    if ((rv = pthread_mutex_init(new_mutex->os.pthread_interproc, &mattr))) {
 #ifdef HAVE_ZOS_PTHREADS
         rv = errno;
 #endif
@@ -536,7 +535,7 @@ static apr_status_t proc_mutex_proc_pthread_acquir
 {
     apr_status_t rv;
 
-    if ((rv = pthread_mutex_lock(mutex->pthread_interproc))) {
+    if ((rv = pthread_mutex_lock(mutex->os.pthread_interproc))) {
 #ifdef HAVE_ZOS_PTHREADS
         rv = errno;
 #endif
@@ -543,7 +542,7 @@ static apr_status_t proc_mutex_proc_pthread_acquir
 #ifdef HAVE_PTHREAD_MUTEX_ROBUST
         /* Okay, our owner died.  Let's try to make it consistent again. */
         if (rv == EOWNERDEAD) {
-            pthread_mutex_consistent_np(mutex->pthread_interproc);
+            pthread_mutex_consistent_np(mutex->os.pthread_interproc);
         }
         else
             return rv;
@@ -559,7 +558,7 @@ static apr_status_t proc_mutex_proc_pthread_tryacq
 {
     apr_status_t rv;
  
-    if ((rv = pthread_mutex_trylock(mutex->pthread_interproc))) {
+    if ((rv = pthread_mutex_trylock(mutex->os.pthread_interproc))) {
 #ifdef HAVE_ZOS_PTHREADS 
         rv = errno;
 #endif
@@ -569,7 +568,7 @@ static apr_status_t proc_mutex_proc_pthread_tryacq
 #ifdef HAVE_PTHREAD_MUTEX_ROBUST
         /* Okay, our owner died.  Let's try to make it consistent again. */
         if (rv == EOWNERDEAD) {
-            pthread_mutex_consistent_np(mutex->pthread_interproc);
+            pthread_mutex_consistent_np(mutex->os.pthread_interproc);
             rv = APR_SUCCESS;
         }
         else
@@ -600,7 +599,7 @@ proc_mutex_proc_pthread_timedacquire(apr_proc_mute
         abstime.tv_sec = apr_time_sec(timeout);
         abstime.tv_nsec = apr_time_usec(timeout) * 1000; /* nanoseconds */
 
-        if ((rv = pthread_mutex_timedlock(mutex->pthread_interproc,
+        if ((rv = pthread_mutex_timedlock(mutex->os.pthread_interproc,
                                           &abstime))) {
 #ifdef HAVE_ZOS_PTHREADS 
             rv = errno;
@@ -611,7 +610,7 @@ proc_mutex_proc_pthread_timedacquire(apr_proc_mute
 #ifdef HAVE_PTHREAD_MUTEX_ROBUST
             /* Okay, our owner died.  Let's try to make it consistent again. */
             if (rv == EOWNERDEAD) {
-                pthread_mutex_consistent_np(mutex->pthread_interproc);
+                pthread_mutex_consistent_np(mutex->os.pthread_interproc);
                 rv = APR_SUCCESS;
             }
             else
@@ -630,7 +629,7 @@ static apr_status_t proc_mutex_proc_pthread_releas
     apr_status_t rv;
 
     mutex->curr_locked = 0;
-    if ((rv = pthread_mutex_unlock(mutex->pthread_interproc))) {
+    if ((rv = pthread_mutex_unlock(mutex->os.pthread_interproc))) {
 #ifdef HAVE_ZOS_PTHREADS
         rv = errno;
 #endif
@@ -650,6 +649,7 @@ static const apr_proc_mutex_unix_lock_methods_t mu
     proc_mutex_proc_pthread_cleanup,
     proc_mutex_no_child_init,
     proc_mutex_no_perms_set,
+    APR_LOCK_PROC_PTHREAD,
     "pthread"
 };
 
@@ -678,7 +678,7 @@ static void proc_mutex_fcntl_setup(void)
 
 static apr_status_t proc_mutex_fcntl_cleanup(void *mutex_)
 {
-    apr_status_t status;
+    apr_status_t status = APR_SUCCESS;
     apr_proc_mutex_t *mutex=mutex_;
 
     if (mutex->curr_locked == 1) {
@@ -687,7 +687,16 @@ static apr_status_t proc_mutex_fcntl_cleanup(void
             return status;
     }
         
-    return apr_file_close(mutex->interproc);
+    if (mutex->interproc) {
+        status = apr_file_close(mutex->interproc);
+    }
+    if (!mutex->closed_by_interproc
+            && mutex->os.crossproc != -1
+            && close(mutex->os.crossproc) == -1
+            && status == APR_SUCCESS) {
+        status = errno;
+    }
+    return status;
 }    
 
 static apr_status_t proc_mutex_fcntl_create(apr_proc_mutex_t *new_mutex,
@@ -713,6 +722,8 @@ static apr_status_t proc_mutex_fcntl_create(apr_pr
         return rv;
     }
 
+    new_mutex->os.crossproc = new_mutex->interproc->filedes;
+    new_mutex->closed_by_interproc = 1;
     new_mutex->curr_locked = 0;
     unlink(new_mutex->fname);
     apr_pool_cleanup_register(new_mutex->pool,
@@ -727,7 +738,7 @@ static apr_status_t proc_mutex_fcntl_acquire(apr_p
     int rc;
 
     do {
-        rc = fcntl(mutex->interproc->filedes, F_SETLKW, &proc_mutex_lock_it);
+        rc = fcntl(mutex->os.crossproc, F_SETLKW, &proc_mutex_lock_it);
     } while (rc < 0 && errno == EINTR);
     if (rc < 0) {
         return errno;
@@ -741,7 +752,7 @@ static apr_status_t proc_mutex_fcntl_tryacquire(ap
     int rc;
 
     do {
-        rc = fcntl(mutex->interproc->filedes, F_SETLK, &proc_mutex_lock_it);
+        rc = fcntl(mutex->os.crossproc, F_SETLK, &proc_mutex_lock_it);
     } while (rc < 0 && errno == EINTR);
     if (rc < 0) {
 #if FCNTL_TRYACQUIRE_EACCES
@@ -770,7 +781,7 @@ static apr_status_t proc_mutex_fcntl_release(apr_p
 
     mutex->curr_locked=0;
     do {
-        rc = fcntl(mutex->interproc->filedes, F_SETLKW, &proc_mutex_unlock_it);
+        rc = fcntl(mutex->os.crossproc, F_SETLKW, &proc_mutex_unlock_it);
     } while (rc < 0 && errno == EINTR);
     if (rc < 0) {
         return errno;
@@ -787,7 +798,7 @@ static apr_status_t proc_mutex_fcntl_perms_set(apr
     if (mutex->fname) {
         if (!(perms & APR_FPROT_GSETID))
             gid = -1;
-        if (fchown(mutex->interproc->filedes, uid, gid) < 0) {
+        if (fchown(mutex->os.crossproc, uid, gid) < 0) {
             return errno;
         }
     }
@@ -809,6 +820,7 @@ static const apr_proc_mutex_unix_lock_methods_t mu
     proc_mutex_fcntl_cleanup,
     proc_mutex_no_child_init,
     proc_mutex_fcntl_perms_set,
+    APR_LOCK_FCNTL,
     "fcntl"
 };
 
@@ -820,7 +832,7 @@ static apr_status_t proc_mutex_flock_release(apr_p
 
 static apr_status_t proc_mutex_flock_cleanup(void *mutex_)
 {
-    apr_status_t status;
+    apr_status_t status = APR_SUCCESS;
     apr_proc_mutex_t *mutex=mutex_;
 
     if (mutex->curr_locked == 1) {
@@ -829,10 +841,18 @@ static apr_status_t proc_mutex_flock_cleanup(void
             return status;
     }
     if (mutex->interproc) { /* if it was opened properly */
-        apr_file_close(mutex->interproc);
+        status = apr_file_close(mutex->interproc);
     }
-    unlink(mutex->fname);
-    return APR_SUCCESS;
+    if (!mutex->closed_by_interproc
+            && mutex->os.crossproc != -1
+            && close(mutex->os.crossproc) == -1
+            && status == APR_SUCCESS) {
+        status = errno;
+    }
+    if (mutex->fname) {
+        unlink(mutex->fname);
+    }
+    return status;
 }    
 
 static apr_status_t proc_mutex_flock_create(apr_proc_mutex_t *new_mutex,
@@ -856,8 +876,11 @@ static apr_status_t proc_mutex_flock_create(apr_pr
  
     if (rv != APR_SUCCESS) {
         proc_mutex_flock_cleanup(new_mutex);
-        return errno;
+        return rv;
     }
+
+    new_mutex->os.crossproc = new_mutex->interproc->filedes;
+    new_mutex->closed_by_interproc = 1;
     new_mutex->curr_locked = 0;
     apr_pool_cleanup_register(new_mutex->pool, (void *)new_mutex,
                               apr_proc_mutex_cleanup,
@@ -870,7 +893,7 @@ static apr_status_t proc_mutex_flock_acquire(apr_p
     int rc;
 
     do {
-        rc = flock(mutex->interproc->filedes, LOCK_EX);
+        rc = flock(mutex->os.crossproc, LOCK_EX);
     } while (rc < 0 && errno == EINTR);
     if (rc < 0) {
         return errno;
@@ -884,7 +907,7 @@ static apr_status_t proc_mutex_flock_tryacquire(ap
     int rc;
 
     do {
-        rc = flock(mutex->interproc->filedes, LOCK_EX | LOCK_NB);
+        rc = flock(mutex->os.crossproc, LOCK_EX | LOCK_NB);
     } while (rc < 0 && errno == EINTR);
     if (rc < 0) {
         if (errno == EWOULDBLOCK || errno == EAGAIN) {
@@ -909,7 +932,7 @@ static apr_status_t proc_mutex_flock_release(apr_p
 
     mutex->curr_locked = 0;
     do {
-        rc = flock(mutex->interproc->filedes, LOCK_UN);
+        rc = flock(mutex->os.crossproc, LOCK_UN);
     } while (rc < 0 && errno == EINTR);
     if (rc < 0) {
         return errno;
@@ -924,13 +947,16 @@ static apr_status_t proc_mutex_flock_child_init(ap
     apr_proc_mutex_t *new_mutex;
     int rv;
 
-    new_mutex = (apr_proc_mutex_t *)apr_palloc(pool, sizeof(apr_proc_mutex_t));
-
-    memcpy(new_mutex, *mutex, sizeof *new_mutex);
-    new_mutex->pool = pool;
     if (!fname) {
         fname = (*mutex)->fname;
+        if (!fname) {
+            return APR_SUCCESS;
+        }
     }
+
+    new_mutex = (apr_proc_mutex_t *)apr_pmemdup(pool, *mutex,
+                                                sizeof(apr_proc_mutex_t));
+    new_mutex->pool = pool;
     new_mutex->fname = apr_pstrdup(pool, fname);
     rv = apr_file_open(&new_mutex->interproc, new_mutex->fname,
                        APR_FOPEN_WRITE, 0, new_mutex->pool);
@@ -937,6 +963,9 @@ static apr_status_t proc_mutex_flock_child_init(ap
     if (rv != APR_SUCCESS) {
         return rv;
     }
+    new_mutex->os.crossproc = new_mutex->interproc->filedes;
+    new_mutex->closed_by_interproc = 1;
+
     *mutex = new_mutex;
     return APR_SUCCESS;
 }
@@ -950,7 +979,7 @@ static apr_status_t proc_mutex_flock_perms_set(apr
     if (mutex->fname) {
         if (!(perms & APR_FPROT_GSETID))
             gid = -1;
-        if (fchown(mutex->interproc->filedes, uid, gid) < 0) {
+        if (fchown(mutex->os.crossproc, uid, gid) < 0) {
             return errno;
         }
     }
@@ -972,6 +1001,7 @@ static const apr_proc_mutex_unix_lock_methods_t mu
     proc_mutex_flock_cleanup,
     proc_mutex_flock_child_init,
     proc_mutex_flock_perms_set,
+    APR_LOCK_FLOCK,
     "flock"
 };
 
@@ -988,12 +1018,35 @@ void apr_proc_mutex_unix_setup_lock(void)
 #endif
 }
 
-static apr_status_t proc_mutex_choose_method(apr_proc_mutex_t *new_mutex, apr_lockmech_e mech)
+static apr_status_t proc_mutex_choose_method(apr_proc_mutex_t *new_mutex,
+                                             apr_lockmech_e mech,
+                                             apr_os_proc_mutex_t *ospmutex)
 {
+#if APR_HAS_PROC_PTHREAD_SERIALIZE
+    new_mutex->os.pthread_interproc = NULL;
+#endif
+#if APR_HAS_POSIXSEM_SERIALIZE
+    new_mutex->os.psem_interproc = NULL;
+#endif
+#if APR_HAS_SYSVSEM_SERIALIZE || APR_HAS_FCNTL_SERIALIZE || APR_HAS_FLOCK_SERIALIZE
+    new_mutex->os.crossproc = -1;
+
+#if APR_HAS_FCNTL_SERIALIZE || APR_HAS_FLOCK_SERIALIZE
+    new_mutex->interproc = NULL;
+    new_mutex->closed_by_interproc = 0;
+#endif
+#endif
+
     switch (mech) {
     case APR_LOCK_FCNTL:
 #if APR_HAS_FCNTL_SERIALIZE
-        new_mutex->inter_meth = &mutex_fcntl_methods;
+        new_mutex->meth = &mutex_fcntl_methods;
+        if (ospmutex) {
+            if (ospmutex->crossproc == -1) {
+                return APR_EINVAL;
+            }
+            new_mutex->os.crossproc = ospmutex->crossproc;
+        }
 #else
         return APR_ENOTIMPL;
 #endif
@@ -1000,7 +1053,13 @@ void apr_proc_mutex_unix_setup_lock(void)
         break;
     case APR_LOCK_FLOCK:
 #if APR_HAS_FLOCK_SERIALIZE
-        new_mutex->inter_meth = &mutex_flock_methods;
+        new_mutex->meth = &mutex_flock_methods;
+        if (ospmutex) {
+            if (ospmutex->crossproc == -1) {
+                return APR_EINVAL;
+            }
+            new_mutex->os.crossproc = ospmutex->crossproc;
+        }
 #else
         return APR_ENOTIMPL;
 #endif
@@ -1007,7 +1066,13 @@ void apr_proc_mutex_unix_setup_lock(void)
         break;
     case APR_LOCK_SYSVSEM:
 #if APR_HAS_SYSVSEM_SERIALIZE
-        new_mutex->inter_meth = &mutex_sysv_methods;
+        new_mutex->meth = &mutex_sysv_methods;
+        if (ospmutex) {
+            if (ospmutex->crossproc == -1) {
+                return APR_EINVAL;
+            }
+            new_mutex->os.crossproc = ospmutex->crossproc;
+        }
 #else
         return APR_ENOTIMPL;
 #endif
@@ -1014,7 +1079,13 @@ void apr_proc_mutex_unix_setup_lock(void)
         break;
     case APR_LOCK_POSIXSEM:
 #if APR_HAS_POSIXSEM_SERIALIZE
-        new_mutex->inter_meth = &mutex_posixsem_methods;
+        new_mutex->meth = &mutex_posixsem_methods;
+        if (ospmutex) {
+            if (ospmutex->psem_interproc == NULL) {
+                return APR_EINVAL;
+            }
+            new_mutex->os.psem_interproc = ospmutex->psem_interproc;
+        }
 #else
         return APR_ENOTIMPL;
 #endif
@@ -1021,7 +1092,13 @@ void apr_proc_mutex_unix_setup_lock(void)
         break;
     case APR_LOCK_PROC_PTHREAD:
 #if APR_HAS_PROC_PTHREAD_SERIALIZE
-        new_mutex->inter_meth = &mutex_proc_pthread_methods;
+        new_mutex->meth = &mutex_proc_pthread_methods;
+        if (ospmutex) {
+            if (ospmutex->pthread_interproc == NULL) {
+                return APR_EINVAL;
+            }
+            new_mutex->os.pthread_interproc = ospmutex->pthread_interproc;
+        }
 #else
         return APR_ENOTIMPL;
 #endif
@@ -1028,15 +1105,45 @@ void apr_proc_mutex_unix_setup_lock(void)
         break;
     case APR_LOCK_DEFAULT:
 #if APR_USE_FLOCK_SERIALIZE
-        new_mutex->inter_meth = &mutex_flock_methods;
+        new_mutex->meth = &mutex_flock_methods;
+        if (ospmutex) {
+            if (ospmutex->crossproc == -1) {
+                return APR_EINVAL;
+            }
+            new_mutex->os.crossproc = ospmutex->crossproc;
+        }
 #elif APR_USE_SYSVSEM_SERIALIZE
-        new_mutex->inter_meth = &mutex_sysv_methods;
+        new_mutex->meth = &mutex_sysv_methods;
+        if (ospmutex) {
+            if (ospmutex->crossproc == -1) {
+                return APR_EINVAL;
+            }
+            new_mutex->os.crossproc = ospmutex->crossproc;
+        }
 #elif APR_USE_FCNTL_SERIALIZE
-        new_mutex->inter_meth = &mutex_fcntl_methods;
+        new_mutex->meth = &mutex_fcntl_methods;
+        if (ospmutex) {
+            if (ospmutex->crossproc == -1) {
+                return APR_EINVAL;
+            }
+            new_mutex->os.crossproc = ospmutex->crossproc;
+        }
 #elif APR_USE_PROC_PTHREAD_SERIALIZE
-        new_mutex->inter_meth = &mutex_proc_pthread_methods;
+        new_mutex->meth = &mutex_proc_pthread_methods;
+        if (ospmutex) {
+            if (ospmutex->pthread_interproc == NULL) {
+                return APR_EINVAL;
+            }
+            new_mutex->os.pthread_interproc = ospmutex->pthread_interproc;
+        }
 #elif APR_USE_POSIXSEM_SERIALIZE
-        new_mutex->inter_meth = &mutex_posixsem_methods;
+        new_mutex->meth = &mutex_posixsem_methods;
+        if (ospmutex) {
+            if (ospmutex->psem_interproc == NULL) {
+                return APR_EINVAL;
+            }
+            new_mutex->os.psem_interproc = ospmutex->psem_interproc;
+        }
 #else
         return APR_ENOTIMPL;
 #endif
@@ -1045,13 +1152,13 @@ void apr_proc_mutex_unix_setup_lock(void)
 #if APR_HAS_PROC_PTHREAD_SERIALIZE \
             && defined(HAVE_PTHREAD_MUTEX_ROBUST) \
             && defined(HAVE_PTHREAD_MUTEX_TIMEDLOCK)
-        new_mutex->inter_meth = &mutex_proc_pthread_methods;
+        new_mutex->meth = &mutex_proc_pthread_methods;
 #elif APR_HAS_SYSVSEM_SERIALIZE \
             && defined(HAVE_SEMTIMEDOP)
-        new_mutex->inter_meth = &mutex_sysv_methods;
+        new_mutex->meth = &mutex_sysv_methods;
 #elif APR_HAS_POSIXSEM_SERIALIZE \
             && defined(HAVE_SEM_TIMEDWAIT)
-        new_mutex->inter_meth = &mutex_posixsem_methods;
+        new_mutex->meth = &mutex_posixsem_methods;
 #else
         return APR_ENOTIMPL;
 #endif
@@ -1067,10 +1174,10 @@ APR_DECLARE(const char *) apr_proc_mutex_defname(v
     apr_status_t rv;
     apr_proc_mutex_t mutex;
 
-    if ((rv = proc_mutex_choose_method(&mutex, APR_LOCK_DEFAULT)) != APR_SUCCESS) {
+    if ((rv = proc_mutex_choose_method(&mutex, APR_LOCK_DEFAULT,
+                                       NULL)) != APR_SUCCESS) {
         return "unknown";
     }
-    mutex.meth = mutex.inter_meth;
 
     return apr_proc_mutex_name(&mutex);
 }
@@ -1079,12 +1186,11 @@ static apr_status_t proc_mutex_create(apr_proc_mut
 {
     apr_status_t rv;
 
-    if ((rv = proc_mutex_choose_method(new_mutex, mech)) != APR_SUCCESS) {
+    if ((rv = proc_mutex_choose_method(new_mutex, mech,
+                                       NULL)) != APR_SUCCESS) {
         return rv;
     }
 
-    new_mutex->meth = new_mutex->inter_meth;
-
     if ((rv = new_mutex->meth->create(new_mutex, fname)) != APR_SUCCESS) {
         return rv;
     }
@@ -1144,6 +1250,11 @@ APR_DECLARE(apr_status_t) apr_proc_mutex_cleanup(v
     return ((apr_proc_mutex_t *)mutex)->meth->cleanup(mutex);
 }
 
+APR_DECLARE(apr_lockmech_e) apr_proc_mutex_mech(apr_proc_mutex_t *mutex)
+{
+    return mutex->meth->mech;
+}
+
 APR_DECLARE(const char *) apr_proc_mutex_name(apr_proc_mutex_t *mutex)
 {
     return mutex->meth->name;
@@ -1176,27 +1287,29 @@ APR_POOL_IMPLEMENT_ACCESSOR(proc_mutex)
 
 /* Implement OS-specific accessors defined in apr_portable.h */
 
-APR_DECLARE(apr_status_t) apr_os_proc_mutex_get(apr_os_proc_mutex_t *ospmutex,
-                                                apr_proc_mutex_t *pmutex)
+APR_DECLARE(apr_status_t) apr_os_proc_mutex_get_ex(apr_os_proc_mutex_t *ospmutex, 
+                                                   apr_proc_mutex_t *pmutex,
+                                                   apr_lockmech_e *mech)
 {
-#if APR_HAS_SYSVSEM_SERIALIZE || APR_HAS_FCNTL_SERIALIZE || APR_HAS_FLOCK_SERIALIZE || APR_HAS_POSIXSEM_SERIALIZE
-    if (pmutex->interproc) {
-        ospmutex->crossproc = pmutex->interproc->filedes;
+    *ospmutex = pmutex->os;
+    if (mech) {
+        *mech = pmutex->meth->mech;
     }
-    else {
-        ospmutex->crossproc = -1;
-    }
-#endif
-#if APR_HAS_PROC_PTHREAD_SERIALIZE
-    ospmutex->pthread_interproc = pmutex->pthread_interproc;
-#endif
     return APR_SUCCESS;
 }
 
-APR_DECLARE(apr_status_t) apr_os_proc_mutex_put(apr_proc_mutex_t **pmutex,
+APR_DECLARE(apr_status_t) apr_os_proc_mutex_get(apr_os_proc_mutex_t *ospmutex,
+                                                apr_proc_mutex_t *pmutex)
+{
+    return apr_os_proc_mutex_get_ex(ospmutex, pmutex, NULL);
+}
+
+APR_DECLARE(apr_status_t) apr_os_proc_mutex_put_ex(apr_proc_mutex_t **pmutex,
                                                 apr_os_proc_mutex_t *ospmutex,
+                                                apr_lockmech_e mech,
                                                 apr_pool_t *pool)
 {
+    apr_status_t rv;
     if (pool == NULL) {
         return APR_ENOPOOL;
     }
@@ -1205,12 +1318,20 @@ APR_POOL_IMPLEMENT_ACCESSOR(proc_mutex)
                                                     sizeof(apr_proc_mutex_t));
         (*pmutex)->pool = pool;
     }
-#if APR_HAS_SYSVSEM_SERIALIZE || APR_HAS_FCNTL_SERIALIZE || APR_HAS_FLOCK_SERIALIZE || APR_HAS_POSIXSEM_SERIALIZE
-    apr_os_file_put(&(*pmutex)->interproc, &ospmutex->crossproc, 0, pool);
+    rv = proc_mutex_choose_method(*pmutex, mech, ospmutex);
+#if APR_HAS_FCNTL_SERIALIZE || APR_HAS_FLOCK_SERIALIZE
+    if (rv == APR_SUCCESS) {
+        rv = apr_os_file_put(&(*pmutex)->interproc, &(*pmutex)->os.crossproc,
+                             0, pool);
+    }
 #endif
-#if APR_HAS_PROC_PTHREAD_SERIALIZE
-    (*pmutex)->pthread_interproc = ospmutex->pthread_interproc;
-#endif
-    return APR_SUCCESS;
+    return rv;
 }
 
+APR_DECLARE(apr_status_t) apr_os_proc_mutex_put(apr_proc_mutex_t **pmutex,
+                                                apr_os_proc_mutex_t *ospmutex,
+                                                apr_pool_t *pool)
+{
+    return apr_os_proc_mutex_put_ex(pmutex, ospmutex, APR_LOCK_DEFAULT, pool);
+}
+
Index: locks/win32/proc_mutex.c
===================================================================
--- locks/win32/proc_mutex.c	(revision 1668004)
+++ locks/win32/proc_mutex.c	(working copy)
@@ -43,6 +43,10 @@ APR_DECLARE(apr_status_t) apr_proc_mutex_create(ap
     HANDLE hMutex;
     void *mutexkey;
 
+    if (mech != APR_LOCK_DEFAULT && mech != APR_LOCK_DEFAULT_TIMED) {
+        return APR_ENOTIMPL;
+    }
+
     /* res_name_from_filename turns fname into a pseduo-name
      * without slashes or backslashes, and prepends the \global
      * prefix on Win2K and later
@@ -220,6 +224,11 @@ APR_DECLARE(const char *) apr_proc_mutex_lockfile(
     return mutex->fname;
 }
 
+APR_DECLARE(apr_lockmech_e) apr_proc_mutex_mech(apr_proc_mutex_t *mutex)
+{
+    return APR_LOCK_DEFAULT_TIMED;
+}
+
 APR_DECLARE(const char *) apr_proc_mutex_name(apr_proc_mutex_t *mutex)
 {
     return apr_proc_mutex_defname();
@@ -236,20 +245,34 @@ APR_POOL_IMPLEMENT_ACCESSOR(proc_mutex)
 
 /* Implement OS-specific accessors defined in apr_portable.h */
 
-APR_DECLARE(apr_status_t) apr_os_proc_mutex_get(apr_os_proc_mutex_t *ospmutex,
-                                                apr_proc_mutex_t *mutex)
+APR_DECLARE(apr_status_t) apr_os_proc_mutex_get_ex(apr_os_proc_mutex_t *ospmutex, 
+                                                   apr_proc_mutex_t *pmutex,
+                                                   apr_lockmech_e *mech)
 {
     *ospmutex = mutex->handle;
+    if (mech) {
+        *mech = APR_LOCK_DEFAULT_TIMED;
+    }
     return APR_SUCCESS;
 }
 
-APR_DECLARE(apr_status_t) apr_os_proc_mutex_put(apr_proc_mutex_t **pmutex,
+APR_DECLARE(apr_status_t) apr_os_proc_mutex_get(apr_os_proc_mutex_t *ospmutex,
+                                                apr_proc_mutex_t *pmutex)
+{
+    return apr_os_proc_mutex_get_ex(ospmutex, pmutex, NULL);
+}
+
+APR_DECLARE(apr_status_t) apr_os_proc_mutex_put_ex(apr_proc_mutex_t **pmutex,
                                                 apr_os_proc_mutex_t *ospmutex,
+                                                apr_lockmech_e mech,
                                                 apr_pool_t *pool)
 {
     if (pool == NULL) {
         return APR_ENOPOOL;
     }
+    if (mech != APR_LOCK_DEFAULT && mech != APR_LOCK_DEFAULT_TIMED) {
+        return APR_ENOTIMPL;
+    }
     if ((*pmutex) == NULL) {
         (*pmutex) = (apr_proc_mutex_t *)apr_palloc(pool,
                                                    sizeof(apr_proc_mutex_t));
@@ -259,3 +282,10 @@ APR_POOL_IMPLEMENT_ACCESSOR(proc_mutex)
     return APR_SUCCESS;
 }
 
+APR_DECLARE(apr_status_t) apr_os_proc_mutex_put(apr_proc_mutex_t **pmutex,
+                                                apr_os_proc_mutex_t *ospmutex,
+                                                apr_pool_t *pool)
+{
+    return apr_os_proc_mutex_put_ex(pmutex, ospmutex, APR_LOCK_DEFAULT_TIMED, pool);
+}
+

Reply via email to