Author: stevehay
Date: Mon Nov  3 08:41:03 2014
New Revision: 1636289

URL: http://svn.apache.org/r1636289
Log:
Decrement interp->refcnt when freeing interpreter in modperl_interp_unselect()

The case where interp->refcnt==1 was not being handled correctly. Prior to 
r1562772 the refcnt was decremented to 0 but then the function returned early, 
wrongly not freeing the interpreter, leading to deadlock in the event MPM. 
Following that change the interpreter was now freed, but the refcnt was wrongly 
no longer decremented.

This change decrements the refcnt (always) and frees the interpreter as well 
(unless the refcnt is still > 0). An extra safety check is also made, to return 
early if the interpreter has already been unselected, although with correct 
refcnting now, we do not expect this to happen.

This patch is based on investigations and a tentative patch suggested by 
Richard M Kandarian:
http://marc.info/?t=140191218700004&r=1&w=2

Modified:
    perl/modperl/trunk/src/modules/perl/modperl_interp.c

Modified: perl/modperl/trunk/src/modules/perl/modperl_interp.c
URL: 
http://svn.apache.org/viewvc/perl/modperl/trunk/src/modules/perl/modperl_interp.c?rev=1636289&r1=1636288&r2=1636289&view=diff
==============================================================================
--- perl/modperl/trunk/src/modules/perl/modperl_interp.c (original)
+++ perl/modperl/trunk/src/modules/perl/modperl_interp.c Mon Nov  3 08:41:03 
2014
@@ -273,17 +273,24 @@ apr_status_t modperl_interp_unselect(voi
     modperl_interp_t *interp = (modperl_interp_t *)data;
     modperl_interp_pool_t *mip = interp->mip;
 
-    MP_ASSERT(interp && MpInterpIN_USE(interp));
+    MP_ASSERT(interp && MpInterpIN_USE(interp) && interp->refcnt > 0);
     MP_TRACE_i(MP_FUNC, "unselect(interp=%pp): refcnt=%d",
                interp, interp->refcnt);
 
-    if (interp->refcnt > 1) {
-        --interp->refcnt;
+    --interp->refcnt;
+
+    if (interp->refcnt > 0) {
         MP_TRACE_i(MP_FUNC, "interp=0x%lx, refcnt=%d -- interp still in use",
                    (unsigned long)interp, interp->refcnt);
         return APR_SUCCESS;
     }
 
+    if (!MpInterpIN_USE(interp)){
+        MP_TRACE_i(MP_FUNC, "interp=0x%pp, refcnt=%d -- interp already not in 
use",
+                   interp, interp->refcnt);
+        return APR_SUCCESS;
+    }
+
     MpInterpIN_USE_Off(interp);
 
     modperl_thx_interp_set(interp->perl, NULL);


Reply via email to