You are viewing a plain text version of this content. The canonical link for it is here.
Posted to modperl-cvs@perl.apache.org by st...@apache.org on 2014/11/03 09:41:04 UTC

svn commit: r1636289 - /perl/modperl/trunk/src/modules/perl/modperl_interp.c

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);