On Tue, Oct 27, 2015 at 12:24:26PM +0200, Niko Tyni wrote:
> On Tue, Oct 27, 2015 at 10:24:23AM +0100, Patrick Matthäi wrote:

> > If it fixes the problem, do you have got an idea which changes to pick up
> > for fixing jessie?
> 
> I haven't looked at it properly yet, but I think there weren't too many
> changes between the versions. I'll follow up on this later when I find
> the time, but it might take a week or so.

I think the two attached patches from upstream r1636289 and r1676417 are
the only likely candidates and should most probably be included together.
They apply as-is to the jessie package.

Any testing would be very welcome.
-- 
Niko Tyni   nt...@debian.org
>From 514800554f704d0fe90fefd70016583099d7944b Mon Sep 17 00:00:00 2001
From: Steve Hay <steve...@apache.org>
Date: Mon, 3 Nov 2014 08:41:03 +0000
Subject: [PATCH] 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

git-svn-id: https://svn.apache.org/repos/asf/perl/modperl/trunk@1636289 13f79535-47bb-0310-9956-ffa450edef68
---
 src/modules/perl/modperl_interp.c | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/src/modules/perl/modperl_interp.c b/src/modules/perl/modperl_interp.c
index 430a2af..a984006 100644
--- a/src/modules/perl/modperl_interp.c
+++ b/src/modules/perl/modperl_interp.c
@@ -273,17 +273,24 @@ apr_status_t modperl_interp_unselect(void *data)
     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);
-- 
2.5.1

>From c7979a708a7be018e5e22680314ea580b2ac2c7a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan=20Kalu=C5=BEa?= <jkal...@apache.org>
Date: Tue, 28 Apr 2015 06:51:12 +0000
Subject: [PATCH] Initialize interp->refcnt to 1 in modperl_interp_select.

Reasoning:
1. All calls of MP_INTERPa do not increment interp->refcnt, so refcnt
   used to be 0 before this commit. But there is always matching
   MP_INTERP_PUTBACK, which calls modperl_interp_unselect which decreases
   the refcnt, so it was possible to get negative refcnt or crash with
   threaded MPMs, because reference counting has been broken.
2. modperl_interp_select increases the refcount if it finds the PerlInterp in
   ccfg, so it makes sense to increase it (it means set to 1) during
   initialization too. Otherwise the refcnt would be incremented for the caller
   in some cases, but wouldn't be in other.

This commit fixes the crash seen on worker MPM when PerlInterp has been used
by two threads and the first one freed PerlInterp during
modperl_interp_unselect.


git-svn-id: https://svn.apache.org/repos/asf/perl/modperl/trunk@1676417 13f79535-47bb-0310-9956-ffa450edef68
---
 src/modules/perl/modperl_interp.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/modules/perl/modperl_interp.c b/src/modules/perl/modperl_interp.c
index a984006..67dd2e4 100644
--- a/src/modules/perl/modperl_interp.c
+++ b/src/modules/perl/modperl_interp.c
@@ -460,7 +460,7 @@ modperl_interp_t *modperl_interp_select(request_rec *r, conn_rec *c,
     interp = modperl_interp_get(s);
     MP_TRACE_i(MP_FUNC, "  --> got %pp (perl=%pp)", interp, interp->perl);
     ++interp->num_requests; /* should only get here once per request */
-    interp->refcnt = 0;
+    interp->refcnt = 1;
 
     /* set context (THX) for this thread */
     PERL_SET_CONTEXT(interp->perl);
-- 
2.5.1

Reply via email to