You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@perl.apache.org by Joe Schaefer <jo...@sunstarsys.com> on 2004/09/28 23:38:33 UTC

[PATCH] Re: segfault ap_save_brigage in the latest 2.0

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org

Re: [PATCH] Re: segfault ap_save_brigage in the latest 2.0

Posted by "Philippe M. Chiasson" <go...@ectoplasm.org>.
Yes, I have seen exactly the problem you are describing hapenning, and
getting away without pool userdata would have fixed it for me.

After just a cursory looking over this patch (not tested or anything)
it looks good.

Joe Schaefer wrote:
> Index: xs/APR/Pool/APR__Pool.h
> ===================================================================
> RCS file: /home/cvspublic/modperl-2.0/xs/APR/Pool/APR__Pool.h,v
> retrieving revision 1.17
> diff -u -r1.17 APR__Pool.h
> --- xs/APR/Pool/APR__Pool.h	14 Jul 2004 23:15:01 -0000	1.17
> +++ xs/APR/Pool/APR__Pool.h	28 Sep 2004 21:32:32 -0000
> @@ -17,6 +17,7 @@
>  
>  typedef struct {
>      SV *sv;
> +    PerlInterpreter *perl;
>  } mpxs_pool_account_t;
>  
>  /* XXX: this implementation has a problem with perl ithreads. if a
> @@ -50,26 +51,10 @@
>  static MP_INLINE apr_status_t
>  mpxs_apr_pool_cleanup(void *cleanup_data)
>  {
> -    mpxs_pool_account_t *data;
> -    apr_pool_userdata_get((void **)&data, MP_APR_POOL_NEW,
> -                          (apr_pool_t *)cleanup_data);
> -    if (!(data && data->sv)) {
> -        /* if there is no data, there is nothing to unset */
> -        MP_POOL_TRACE(MP_FUNC, "this pool seems to be destroyed already");
> -    }
> -    else {
> -        MP_POOL_TRACE(MP_FUNC,
> -                      "pool 0x%lx contains a valid sv 0x%lx, invalidating it",
> -                      (unsigned long)data->sv, (unsigned long)cleanup_data);
> -
> -        /* invalidate all Perl objects referencing this sv */
> -        SvIVX(data->sv) = 0;
> -
> -        /* invalidate the reference stored in the pool */
> -        data->sv = NULL;
> -        /* data->sv will go away by itself when all objects will go away */
> -    }
> -
> +    mpxs_pool_account_t *acct = cleanup_data;
> +    dTHXa(acct->perl);
> +    mg_free(acct->sv);
> +    SvIVX(acct->sv) = 0;
>      return APR_SUCCESS;
>  }
>  
> @@ -116,9 +101,6 @@
>       * mess, trying to destroy an already destroyed pool or even worse
>       * a pool allocate in the place of the old one.
>       */
> -    apr_pool_cleanup_register(child_pool, (void *)child_pool,
> -                              mpxs_apr_pool_cleanup,
> -                              apr_pool_cleanup_null);
>  #if APR_POOL_DEBUG
>      /* child <-> parent <-> ... <-> top ancestry traversal */
>      {
> @@ -139,17 +121,22 @@
>  #endif
>  
>      {
> -        mpxs_pool_account_t *data =
> -            (mpxs_pool_account_t *)apr_pcalloc(child_pool, sizeof(*data));
> -
>          SV *rv = sv_setref_pv(NEWSV(0, 0), "APR::Pool", (void*)child_pool);
> +        SV *sv = SvRV(rv);
> +        mpxs_pool_account_t *acct = apr_palloc(child_pool, sizeof *acct);
>  
> -        data->sv = SvRV(rv);
> +        acct->sv = sv;
> +        acct->perl = aTHX;
> +
> +        sv_magic(sv, Nullsv, PERL_MAGIC_ext, "APR::Pool", sizeof("APR::Pool"));
>  
> -        MP_POOL_TRACE(MP_FUNC, "sub-pool p: 0x%lx, sv: 0x%lx, rv: 0x%lx",
> -                      (unsigned long)child_pool, data->sv, rv);
>  
> -        apr_pool_userdata_set(data, MP_APR_POOL_NEW, NULL, child_pool);
> +        apr_pool_cleanup_register(child_pool, (void *)acct,
> +                                  mpxs_apr_pool_cleanup,
> +                                  apr_pool_cleanup_null);
> +
> +        MP_POOL_TRACE(MP_FUNC, "sub-pool p: 0x%lx, sv: 0x%lx, rv: 0x%lx",
> +                      (unsigned long)child_pool, sv, rv);
>  
>          return rv;
>      }
> @@ -158,10 +145,10 @@
>  static MP_INLINE void mpxs_APR__Pool_clear(pTHX_ SV *obj)
>  {
>      apr_pool_t *p = mp_xs_sv2_APR__Pool(obj);
> -    mpxs_pool_account_t *data;
> +    SV *sv = SvRV(obj);
> +    mpxs_pool_account_t *acct;
>  
> -    apr_pool_userdata_get((void **)&data, MP_APR_POOL_NEW, p);
> -    if (!(data && data->sv)) {
> +    if (mg_find(sv, PERL_MAGIC_ext) == NULL) {
>          MP_POOL_TRACE(MP_FUNC, "parent pool (0x%lx) is a core pool",
>                        (unsigned long)p);
>          apr_pool_clear(p);
> @@ -171,20 +158,24 @@
>      MP_POOL_TRACE(MP_FUNC,
>                    "parent pool (0x%lx) is a custom pool, sv 0x%lx",
>                    (unsigned long)p,
> -                  (unsigned long)data->sv);
> +                  (unsigned long)sv);
>  
>      apr_pool_clear(p);
>  
> -    /* apr_pool_clear removes all the user data, so we need to restore
> +    /* apr_pool_clear removes all the cleanup, so we need to restore
>       * it. Since clear triggers mpxs_apr_pool_cleanup call, our
>       * object's guts get nuked too, so we need to restore them too */
>  
>      /* this is sv_setref_pv, but for an existing object */
> -    sv_setiv(newSVrv(obj, "APR::Pool"), PTR2IV((void*)p));
> -    data->sv = SvRV(obj);
> +    sv_magic(sv, Nullsv, PERL_MAGIC_ext, "APR::Pool", sizeof("APR::Pool"));
> +    SvIVX(sv) = (IV)p;
> +    acct = apr_palloc(p, sizeof *acct);
> +    acct->sv = sv;
> +    acct->perl = aTHX;
>  
> -    /* reinstall the user data */
> -    apr_pool_userdata_set(data, MP_APR_POOL_NEW, NULL, p);
> +    apr_pool_cleanup_register(p, (void *)acct,
> +                              mpxs_apr_pool_cleanup,
> +                              apr_pool_cleanup_null);
>  }
>  
>  
> @@ -294,30 +285,7 @@
>      apr_pool_t *parent_pool = apr_pool_parent_get(child_pool);
>  
>      if (parent_pool) {
> -        /* ideally this should be done by mp_xs_APR__Pool_2obj. Though
> -         * since most of the time we don't use custom pools, we don't
> -         * want the overhead of reading and writing pool's userdata in
> -         * the general case. therefore we do it here and in
> -         * mpxs_apr_pool_create. Though if there are any other
> -         * functions, that return perl objects whose guts include a
> -         * reference to a custom pool, they must do the ref-counting
> -         * as well.
> -         */
> -        mpxs_pool_account_t *data;
> -        apr_pool_userdata_get((void **)&data, MP_APR_POOL_NEW, parent_pool);
> -        if (data && data->sv) {
> -            MP_POOL_TRACE(MP_FUNC,
> -                          "parent pool (0x%lx) is a custom pool, sv 0x%lx",
> -                          (unsigned long)parent_pool,
> -                          (unsigned long)data->sv);
> -
> -            return newRV_inc(data->sv);
> -        }
> -        else {
> -            MP_POOL_TRACE(MP_FUNC, "parent pool (0x%lx) is a core pool",
> -                          (unsigned long)parent_pool);
> -            return SvREFCNT_inc(mp_xs_APR__Pool_2obj(parent_pool));
> -        }
> +        return SvREFCNT_inc(mp_xs_APR__Pool_2obj(parent_pool));
>      }
>      else {
>          MP_POOL_TRACE(MP_FUNC, "pool (0x%lx) has no parents",
> @@ -335,11 +303,18 @@
>      apr_pool_t *p;
>      SV *sv = SvRV(obj);
>  
> +    p = mpxs_sv_object_deref(obj, apr_pool_t);
> +
> +    if (mg_find(sv, PERL_MAGIC_ext))
> +        apr_pool_destroy(p);
> +
> +#if 0
> +
>      /* MP_POOL_TRACE(MP_FUNC, "DESTROY 0x%lx-0x%lx",       */
>      /*              (unsigned long)obj,(unsigned long)sv); */
>      /* do_sv_dump(0, Perl_debug_log, obj, 0, 4, FALSE, 0); */
>  
> -    p = mpxs_sv_object_deref(obj, apr_pool_t);
> +
>      if (!p) {
>          /* non-custom pool */
>          MP_POOL_TRACE(MP_FUNC, "skip apr_pool_destroy: not a custom pool");
> @@ -367,5 +342,7 @@
>                            SvREFCNT(sv));
>          }
>      }
> +
> +#endif
>  }
>  
> 
> 
> 
> 
> 
> ------------------------------------------------------------------------
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
> For additional commands, e-mail: dev-help@perl.apache.org

-- 
--------------------------------------------------------------------------------
Philippe M. Chiasson m/gozer\@(apache|cpan|ectoplasm)\.org/ GPG KeyID : 88C3A5A5
http://gozer.ectoplasm.org/     F9BF E0C2 480E 7680 1AE5 3631 CB32 A107 88C3A5A5

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org


Re: [PATCH] Re: segfault ap_save_brigage in the latest 2.0

Posted by Geoffrey Young <ge...@modperlcookbook.org>.
> +        # the APR_EGENERAL error string changed for APR 1.0
> +        my $egeneral = "Error string not specified yet";
> +        $egeneral = "Internal error"
> +            if need_min_apache_version('2.1.0');

this should be have_min_apache_version() instead.  basically, use the need*
variants in calls to plan() and have* variants everywhere else, as need*
adds to the global test skip message, which can leak across tests.

other than that, looks great :)

I'm looking into the content_length failure now.  what I think is happening
there is that we coded it as httpd behaved at the moment, but that something
has recently changed over there and I'm just now catching up on my email.

as an aside, I think we kind of informally agreed that the tests in t/apache
were for testing internal apache things in an attempt to let us know when
some basic httpd functionality changed that we should be knowing about.  so,
in this case, that the behavior of a handler with a zero content length has
changed wrt the C-L header isn't as important to mod_perl as it is to us
understanding things when users report problems (which was the reason we
wrote this particular test IIRC).

anyway, I'm building against current cvs now after a few days of travelling,
so I hope to have a solution for that test soon.

--Geoff

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org


Re: [PATCH] Re: segfault ap_save_brigage in the latest 2.0

Posted by Geoffrey Young <ge...@modperlcookbook.org>.

Joe Orton wrote:
> On Wed, Sep 29, 2004 at 11:43:27PM -0400, Stas Bekman wrote:
> 
>>Joe Schaefer wrote:
>>
>>>>>t/api/aplog.t                                  35    1   2.86%  24
> 
> 
> I wrote a fix for this one the other day since it was easy.
>

committed, thanks!

--Geoff

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org


Re: [PATCH] Re: segfault ap_save_brigage in the latest 2.0

Posted by Joe Orton <jo...@redhat.com>.
On Wed, Sep 29, 2004 at 11:43:27PM -0400, Stas Bekman wrote:
> Joe Schaefer wrote:
> >>>t/api/aplog.t                                  35    1   2.86%  24

I wrote a fix for this one the other day since it was easy.

--- response/TestAPI/aplog.pm	24 Sep 2004 19:55:35 -0000	1.21
+++ response/TestAPI/aplog.pm	28 Sep 2004 12:19:36 -0000
@@ -74,11 +74,16 @@
             qr/: log_serror test 1$/m,
             '$s->log_serror(__FILE__, __LINE__, LOG_DEBUG...)';
 
+        # the APR_EGENERAL error string changed for APR 1.0
+        my $egeneral = "Error string not specified yet";
+        $egeneral = "Internal error"
+            if need_min_apache_version('2.1.0');
+
         t_server_log_warn_is_expected();
         $s->log_serror(Apache::Log::LOG_MARK, Apache::LOG_DEBUG,
                        APR::EGENERAL, "log_serror test 2");
         ok t_cmp $logdiff->diff,
-            qr/Error string not specified yet: log_serror test 2/,
+            qr/$egeneral: log_serror test 2/,
             '$s->log_serror(LOG_MARK, LOG_DEBUG, APR::EGENERAL...)';
     }
 

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org


Re: [PATCH] Re: segfault ap_save_brigage in the latest 2.0

Posted by Stas Bekman <st...@stason.org>.
Joe Schaefer wrote:
> Stas Bekman <st...@stason.org> writes:
> 
> 
>>Joe Schaefer wrote:
>>
>>>...  That doesn't mean all the tests pass,
>>>Failed Test                      Stat Wstat Total Fail  Failed  List of Failed
>>>-------------------------------------------------------------------------------
>>>t/apache/content_length_header.t               27    3  11.11%  2 5 17
>>>t/api/aplog.t                                  35    1   2.86%  24
>>>4 tests skipped.
>>>Failed 2/219 test scripts, 99.09% okay. 4/4208 subtests failed, 99.90% okay.
>>
>>But what about the verbose run and the error_log and the usual t/REPORT output?
> 
> 
> I'm fairly certain I've posted those previously, but if not, it's
> no big deal since I know what's going on there. 

You mean you know the cause for these failures and you will post a fix as 
well. I just can't tell what the problem is, since they don't fail for me. 
But if you are handling those, then no need to post anything extra :) 
Thanks Joe.

> However, you've
> missed my point, which was that the above is result is absolutely
> wonderful, given a week's worth of results like this one,

Excellent, I didn't miss your point, just thought you needed help to get 
100% pass :)


-- 
__________________________________________________________________
Stas Bekman            JAm_pH ------> Just Another mod_perl Hacker
http://stason.org/     mod_perl Guide ---> http://perl.apache.org
mailto:stas@stason.org http://use.perl.org http://apacheweek.com
http://modperlbook.org http://apache.org   http://ticketmaster.com

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org


Re: [PATCH] Re: segfault ap_save_brigage in the latest 2.0

Posted by Joe Schaefer <jo...@sunstarsys.com>.
Stas Bekman <st...@stason.org> writes:

> Joe Schaefer wrote:
> >...  That doesn't mean all the tests pass,
> > Failed Test                      Stat Wstat Total Fail  Failed  List of Failed
> > -------------------------------------------------------------------------------
> > t/apache/content_length_header.t               27    3  11.11%  2 5 17
> > t/api/aplog.t                                  35    1   2.86%  24
> > 4 tests skipped.
> > Failed 2/219 test scripts, 99.09% okay. 4/4208 subtests failed, 99.90% okay.
> 
> But what about the verbose run and the error_log and the usual t/REPORT output?

I'm fairly certain I've posted those previously, but if not, it's
no big deal since I know what's going on there.  However, you've
missed my point, which was that the above is result is absolutely
wonderful, given a week's worth of results like this one, generated
from today's mp2/httpd/apr cvs:

Failed Test                      Stat Wstat Total Fail  Failed  List of Failed
-------------------------------------------------------------------------------
t/apache/content_length_header.t               27    3  11.11%  2 5 17
t/api/aplog.t                                  35    1   2.86%  24
t/filter/both_str_req_add.t                     1    1 100.00%  1
t/filter/out_bbs_filebucket.t                  10    2  20.00%  1-2
t/modules/proxy.t                 255 65280     1    2 200.00%  1
t/perl/ithreads.t                               4    3  75.00%  2-4
2 tests skipped.
Failed 6/218 test scripts, 97.25% okay. 11/4198 subtests failed, 99.74% okay.
[warning] server localhost.localdomain:9500 shutdown
[warning] port 9500 still in use...
done
[  error] error running tests (please examine t/logs/error_log)
[   info] an old core file has been found: /home/smoke/src/apache/modperl-2.0/t/core.22806
[   info] an old core file has been found: /home/smoke/src/apache/modperl-2.0/t/core.25623
[   info] an old core file has been found: /home/smoke/src/apache/modperl-2.0/t/core.31268
[   info] an old core file has been found: /home/smoke/src/apache/modperl-2.0/t/core.2722
[  error] oh crap, server dumped core
[  error] for stacktrace, run: gdb /home/smoke/apache/httpd-worker/bin/httpd -core /home/smoke/src/apache/modperl-2.0/t/core.9756
+--------------------------------------------------------+
| Please file a bug report: http://perl.apache.org/bugs/ |
+--------------------------------------------------------+


-- 
Joe Schaefer


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org


Re: [PATCH] Re: segfault ap_save_brigage in the latest 2.0

Posted by Stas Bekman <st...@stason.org>.
Joe Schaefer wrote:
>...  That doesn't mean all the tests pass,
> 
> Failed Test                      Stat Wstat Total Fail  Failed  List of Failed
> -------------------------------------------------------------------------------
> t/apache/content_length_header.t               27    3  11.11%  2 5 17
> t/api/aplog.t                                  35    1   2.86%  24
> 4 tests skipped.
> Failed 2/219 test scripts, 99.09% okay. 4/4208 subtests failed, 99.90% okay.

But what about the verbose run and the error_log and the usual t/REPORT 
output?


-- 
__________________________________________________________________
Stas Bekman            JAm_pH ------> Just Another mod_perl Hacker
http://stason.org/     mod_perl Guide ---> http://perl.apache.org
mailto:stas@stason.org http://use.perl.org http://apacheweek.com
http://modperlbook.org http://apache.org   http://ticketmaster.com

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org


Re: [PATCH] Re: segfault ap_save_brigage in the latest 2.0

Posted by Joe Schaefer <jo...@sunstarsys.com>.
Stas Bekman <st...@stason.org> writes:

> Joe Schaefer wrote:
> 
> > Looks good.  It tests fine, so I tried to include it in the patch,
> > but alas: 
> >   $ cvs add pool_lifetime.t
> >   cvs [server aborted]: "add" requires write access to the repository
> 
> Right, but you should run:
> 
> perl util/getdiff.pl newfile1 newfile2 ...

Thanks.  The good news (for me anyway) is that with the combined
patches I posted today, I'm once again able to complete the test 
suite without segfaults- something I haven't been able to do reliably
for over a week now.  That doesn't mean all the tests pass, 

Failed Test                      Stat Wstat Total Fail  Failed  List of Failed
-------------------------------------------------------------------------------
t/apache/content_length_header.t               27    3  11.11%  2 5 17
t/api/aplog.t                                  35    1   2.86%  24
4 tests skipped.
Failed 2/219 test scripts, 99.09% okay. 4/4208 subtests failed, 99.90% okay.


but at least the flaky behavior that have been me over 
the last two weeks is gone for now, assuming the patches
are ok with you guys.  If not, let me know and I'll fix+
post them again...

-- 
Joe Schaefer


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org


Re: [PATCH] Re: segfault ap_save_brigage in the latest 2.0

Posted by Stas Bekman <st...@stason.org>.
Joe Schaefer wrote:

> Looks good.  It tests fine, so I tried to include it 
> in the patch, but alas:
> 
>   $ cvs add pool_lifetime.t
>   cvs [server aborted]: "add" requires write access to the repository

Right, but you should run:

perl util/getdiff.pl newfile1 newfile2 ...

and it'll create a diff for new files against /dev/null and give the 
normal diff for files which are already under the cvs control.

-- 
__________________________________________________________________
Stas Bekman            JAm_pH ------> Just Another mod_perl Hacker
http://stason.org/     mod_perl Guide ---> http://perl.apache.org
mailto:stas@stason.org http://use.perl.org http://apacheweek.com
http://modperlbook.org http://apache.org   http://ticketmaster.com

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org


Re: [PATCH] Re: segfault ap_save_brigage in the latest 2.0

Posted by Joe Schaefer <jo...@sunstarsys.com>.
"Philippe M. Chiasson" <go...@ectoplasm.org> writes:

> Looks good, I am going to give it a spin shortly. Only one note
> after looking over this patch. I'd keep the definition of
> mpxs_pool_account_t at the top
> 
> typedef struct {
>      SV *sv;
> #ifdef USE_ITHREADS
>      PerlInterpreter *perl;
>      modperl_interp_t *interp;
> #endif
> } mpxs_pool_account_t;
> 

+1.

[...]

> > +#define MP_APR_POOL_SV_DROPS_OWNERSHIP(acct) do {               \
> > +    dTHXa(acct->perl);                                          \
> > +    mg_free(acct->sv);                                          \
> > +    SvIVX(acct->sv) = 0;                                        \
> > +    if (modperl_opt_interp_unselect && acct->interp) {          \
> > +        /* this will decrement the interp refcnt until          \
> > +         * there are no more references, in which case          \
> > +         * the interpreter will be putback into the mip         \
> > +         */                                                     \
> > +        (void)modperl_opt_interp_unselect(acct->interp);        \
> > +    }                                                           \
> > +} while (0)
> > +
> > +
> > +#ifdef USE_ITHREADS

Oops- MP_APR_POOL_SV_DROPS_OWNERSHIP also needs to be inside an 

#ifdef USE_ITHREADS

because of the acct->interp call.  The non-ithreads version should 
probably look like this:

#define MP_APR_POOL_SV_DROPS_OWNERSHIP(acct) do {               \
    mg_free(acct->sv);                                          \
    SvIVX(acct->sv) = 0;                                        \
} while (0)


-- 
Joe Schaefer


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org


Re: [PATCH] Re: segfault ap_save_brigage in the latest 2.0

Posted by "Philippe M. Chiasson" <go...@ectoplasm.org>.

Joe Schaefer wrote:
> "Philippe M. Chiasson" <go...@ectoplasm.org> writes:
> 
> 
>>I've tested it hapilly and it is both a simpler implementation
>>and gets away with quite an annoying bug, so I'd like to see
>>it integrated with a few tweaks.
> 
> 
> OK, I've cleaned it up with a few macros as you
> suggested.  Patch below...
> 
> 
>>- At least one test case for this (check my post 
>>http://marc.theaimsgroup.com/?l=apache-modperl-dev&m=109596770111457&w=2
> 
> 
> Looks good.  It tests fine, so I tried to include it 
> in the patch, but alas:
> 
>   $ cvs add pool_lifetime.t
>   cvs [server aborted]: "add" requires write access to the repository

Looks good, I am going to give it a spin shortly. Only one note after
looking over this patch. I'd keep the definition of mpxs_pool_account_t
at the top

typedef struct {
     SV *sv;
#ifdef USE_ITHREADS
     PerlInterpreter *perl;
     modperl_interp_t *interp;
#endif
} mpxs_pool_account_t;

instead of having to completely different and separated definitions. It's
a small change, but I think it clarify things a little bit. Apart from that,
patch does look quite good.

> 
> Index: xs/APR/Pool/APR__Pool.h
> ===================================================================
> RCS file: /home/cvspublic/modperl-2.0/xs/APR/Pool/APR__Pool.h,v
> retrieving revision 1.17
> diff -u -r1.17 APR__Pool.h
> --- xs/APR/Pool/APR__Pool.h	14 Jul 2004 23:15:01 -0000	1.17
> +++ xs/APR/Pool/APR__Pool.h	30 Sep 2004 01:14:04 -0000
> @@ -15,10 +15,6 @@
>  
>  #define MP_APR_POOL_NEW "APR::Pool::new"
>  
> -typedef struct {
> -    SV *sv;
> -} mpxs_pool_account_t;
> -
>  /* XXX: this implementation has a problem with perl ithreads. if a
>   * custom pool is allocated, and then a thread is spawned we now have
>   * two copies of the pool object, each living in a different perl
> @@ -33,6 +29,82 @@
>   *   that?) may be we can skip those?
>   */
>  
> +#ifndef MP_SOURCE_SCAN
> +#include "apr_optional.h"
> +static
> +APR_OPTIONAL_FN_TYPE(modperl_interp_unselect) *modperl_opt_interp_unselect;
> +#endif
> +
> +
> +#define MP_APR_POOL_SV_HAS_OWNERSHIP(sv) (mg_find(sv, PERL_MAGIC_ext) != NULL)
> +
> +#define MP_APR_POOL_SV_DROPS_OWNERSHIP(acct) do {               \
> +    dTHXa(acct->perl);                                          \
> +    mg_free(acct->sv);                                          \
> +    SvIVX(acct->sv) = 0;                                        \
> +    if (modperl_opt_interp_unselect && acct->interp) {          \
> +        /* this will decrement the interp refcnt until          \
> +         * there are no more references, in which case          \
> +         * the interpreter will be putback into the mip         \
> +         */                                                     \
> +        (void)modperl_opt_interp_unselect(acct->interp);        \
> +    }                                                           \
> +} while (0)
> +
> +
> +#ifdef USE_ITHREADS
> +
> +typedef struct {
> +    SV *sv;
> +    PerlInterpreter *perl;
> +    modperl_interp_t *interp;
> +} mpxs_pool_account_t;
> +
> +
> +#define MP_APR_POOL_SV_TAKES_OWNERSHIP(SV, P) do {              \
> +    mpxs_pool_account_t *acct = apr_palloc(P, sizeof *acct);    \
> +    acct->sv = SV;                                              \
> +    acct->perl = aTHX;                                          \
> +    SvIVX(SV) = PTR2IV(P);                                      \
> +                                                                \
> +    sv_magic(SV, Nullsv, PERL_MAGIC_ext,                        \
> +             MP_APR_POOL_NEW, sizeof(MP_APR_POOL_NEW));         \
> +                                                                \
> +    apr_pool_cleanup_register(P, (void *)acct,                  \
> +                              mpxs_apr_pool_cleanup,            \
> +                              apr_pool_cleanup_null);           \
> +                                                                \
> +    /* make sure interpreter is not putback into the mip        \
> +     * until this cleanup has run.                              \
> +     */                                                         \
> +    if ((acct->interp = MP_THX_INTERP_GET(aTHX))) {             \
> +        acct->interp->refcnt++;                                 \
> +    }                                                           \
> +} while (0)
> +
> +#else
> +
> +typedef struct {
> +    SV *sv;
> +} mpxs_pool_account_t;
> +
> +
> +#define MP_APR_POOL_SV_TAKES_OWNERSHIP(SV, P) do {              \
> +    mpxs_pool_account_t *acct = apr_palloc(P, sizeof *acct);    \
> +    acct->sv = SV;                                              \
> +    SvIVX(SV) = PTR2IV(P);                                      \
> +                                                                \
> +    sv_magic(SV, Nullsv, PERL_MAGIC_ext,                        \
> +              MP_APR_POOL_NEW, sizeof(MP_APR_POOL_NEW));        \
> +                                                                \
> +    apr_pool_cleanup_register(P, (void *)acct,                  \
> +                              mpxs_apr_pool_cleanup,            \
> +                              apr_pool_cleanup_null);           \
> +} while (0)
> +
> +#endif
> +
> +
>  /* XXX: should we make it a new global tracing category
>   * MOD_PERL_TRACE=p for tracing pool management? */
>  #define MP_POOL_TRACE_DO 0
> @@ -50,26 +122,8 @@
>  static MP_INLINE apr_status_t
>  mpxs_apr_pool_cleanup(void *cleanup_data)
>  {
> -    mpxs_pool_account_t *data;
> -    apr_pool_userdata_get((void **)&data, MP_APR_POOL_NEW,
> -                          (apr_pool_t *)cleanup_data);
> -    if (!(data && data->sv)) {
> -        /* if there is no data, there is nothing to unset */
> -        MP_POOL_TRACE(MP_FUNC, "this pool seems to be destroyed already");
> -    }
> -    else {
> -        MP_POOL_TRACE(MP_FUNC,
> -                      "pool 0x%lx contains a valid sv 0x%lx, invalidating it",
> -                      (unsigned long)data->sv, (unsigned long)cleanup_data);
> -
> -        /* invalidate all Perl objects referencing this sv */
> -        SvIVX(data->sv) = 0;
> -
> -        /* invalidate the reference stored in the pool */
> -        data->sv = NULL;
> -        /* data->sv will go away by itself when all objects will go away */
> -    }
> -
> +    mpxs_pool_account_t *acct = cleanup_data;
> +    MP_APR_POOL_SV_DROPS_OWNERSHIP(acct);

MP_APR_POOL_SV_DROPS_OWNERSHIP((mpxs_pool_account_t *)cleanup_data)

>      return APR_SUCCESS;
>  }
>  
> @@ -116,9 +170,6 @@
>       * mess, trying to destroy an already destroyed pool or even worse
>       * a pool allocate in the place of the old one.
>       */
> -    apr_pool_cleanup_register(child_pool, (void *)child_pool,
> -                              mpxs_apr_pool_cleanup,
> -                              apr_pool_cleanup_null);
>  #if APR_POOL_DEBUG
>      /* child <-> parent <-> ... <-> top ancestry traversal */
>      {
> @@ -139,17 +190,13 @@
>  #endif
>  
>      {
> -        mpxs_pool_account_t *data =
> -            (mpxs_pool_account_t *)apr_pcalloc(child_pool, sizeof(*data));
> -
>          SV *rv = sv_setref_pv(NEWSV(0, 0), "APR::Pool", (void*)child_pool);
> +        SV *sv = SvRV(rv);
>  
> -        data->sv = SvRV(rv);
> +        MP_APR_POOL_SV_TAKES_OWNERSHIP(sv, child_pool);
>  
>          MP_POOL_TRACE(MP_FUNC, "sub-pool p: 0x%lx, sv: 0x%lx, rv: 0x%lx",
> -                      (unsigned long)child_pool, data->sv, rv);
> -
> -        apr_pool_userdata_set(data, MP_APR_POOL_NEW, NULL, child_pool);
> +                      (unsigned long)child_pool, sv, rv);
>  
>          return rv;
>      }
> @@ -158,10 +205,9 @@
>  static MP_INLINE void mpxs_APR__Pool_clear(pTHX_ SV *obj)
>  {
>      apr_pool_t *p = mp_xs_sv2_APR__Pool(obj);
> -    mpxs_pool_account_t *data;
> +    SV *sv = SvRV(obj);
>  
> -    apr_pool_userdata_get((void **)&data, MP_APR_POOL_NEW, p);
> -    if (!(data && data->sv)) {
> +    if (!MP_APR_POOL_SV_HAS_OWNERSHIP(sv)) {
>          MP_POOL_TRACE(MP_FUNC, "parent pool (0x%lx) is a core pool",
>                        (unsigned long)p);
>          apr_pool_clear(p);
> @@ -171,20 +217,15 @@
>      MP_POOL_TRACE(MP_FUNC,
>                    "parent pool (0x%lx) is a custom pool, sv 0x%lx",
>                    (unsigned long)p,
> -                  (unsigned long)data->sv);
> +                  (unsigned long)sv);
>  
>      apr_pool_clear(p);
>  
> -    /* apr_pool_clear removes all the user data, so we need to restore
> +    /* apr_pool_clear removes all the cleanups, so we need to restore
>       * it. Since clear triggers mpxs_apr_pool_cleanup call, our
>       * object's guts get nuked too, so we need to restore them too */
>  
> -    /* this is sv_setref_pv, but for an existing object */
> -    sv_setiv(newSVrv(obj, "APR::Pool"), PTR2IV((void*)p));
> -    data->sv = SvRV(obj);
> -
> -    /* reinstall the user data */
> -    apr_pool_userdata_set(data, MP_APR_POOL_NEW, NULL, p);
> +    MP_APR_POOL_SV_TAKES_OWNERSHIP(sv, p);
>  }
>  
>  
> @@ -203,11 +244,6 @@
>   * @param data   internal storage
>   */
>  
> -#ifndef MP_SOURCE_SCAN
> -#include "apr_optional.h"
> -static
> -APR_OPTIONAL_FN_TYPE(modperl_interp_unselect) *modperl_opt_interp_unselect;
> -#endif
>  
>  static apr_status_t mpxs_cleanup_run(void *data)
>  {
> @@ -294,30 +330,7 @@
>      apr_pool_t *parent_pool = apr_pool_parent_get(child_pool);
>  
>      if (parent_pool) {
> -        /* ideally this should be done by mp_xs_APR__Pool_2obj. Though
> -         * since most of the time we don't use custom pools, we don't
> -         * want the overhead of reading and writing pool's userdata in
> -         * the general case. therefore we do it here and in
> -         * mpxs_apr_pool_create. Though if there are any other
> -         * functions, that return perl objects whose guts include a
> -         * reference to a custom pool, they must do the ref-counting
> -         * as well.
> -         */
> -        mpxs_pool_account_t *data;
> -        apr_pool_userdata_get((void **)&data, MP_APR_POOL_NEW, parent_pool);
> -        if (data && data->sv) {
> -            MP_POOL_TRACE(MP_FUNC,
> -                          "parent pool (0x%lx) is a custom pool, sv 0x%lx",
> -                          (unsigned long)parent_pool,
> -                          (unsigned long)data->sv);
> -
> -            return newRV_inc(data->sv);
> -        }
> -        else {
> -            MP_POOL_TRACE(MP_FUNC, "parent pool (0x%lx) is a core pool",
> -                          (unsigned long)parent_pool);
> -            return SvREFCNT_inc(mp_xs_APR__Pool_2obj(parent_pool));
> -        }
> +        return SvREFCNT_inc(mp_xs_APR__Pool_2obj(parent_pool));
>      }
>      else {
>          MP_POOL_TRACE(MP_FUNC, "pool (0x%lx) has no parents",
> @@ -330,42 +343,14 @@
>   * destroy a pool
>   * @param obj    an APR::Pool object
>   */
> +
>  static MP_INLINE void mpxs_apr_pool_DESTROY(pTHX_ SV *obj)
>  {
> -    apr_pool_t *p;
>      SV *sv = SvRV(obj);
>  
> -    /* MP_POOL_TRACE(MP_FUNC, "DESTROY 0x%lx-0x%lx",       */
> -    /*              (unsigned long)obj,(unsigned long)sv); */
> -    /* do_sv_dump(0, Perl_debug_log, obj, 0, 4, FALSE, 0); */
> -
> -    p = mpxs_sv_object_deref(obj, apr_pool_t);
> -    if (!p) {
> -        /* non-custom pool */
> -        MP_POOL_TRACE(MP_FUNC, "skip apr_pool_destroy: not a custom pool");
> -        return;
> -    }
> -
> -    if (sv && SvOK(sv)) {
> -        mpxs_pool_account_t *data;
> -
> -        apr_pool_userdata_get((void **)&data, MP_APR_POOL_NEW, p);
> -        if (!(data && data->sv)) {
> -            MP_POOL_TRACE(MP_FUNC, "skip apr_pool_destroy: no sv found");
> -            return;
> -        }
> -
> -        if (SvREFCNT(sv) == 1) {
> -            MP_POOL_TRACE(MP_FUNC, "call apr_pool_destroy: last reference");
> -            apr_pool_destroy(p);
> -        }
> -        else {
> -            /* when the pool object dies, sv's ref count decrements
> -             * itself automatically */
> -            MP_POOL_TRACE(MP_FUNC,
> -                          "skip apr_pool_destroy: refcount > 1 (%d)",
> -                          SvREFCNT(sv));
> -        }
> +    if (MP_APR_POOL_SV_HAS_OWNERSHIP(sv)) {
> +        apr_pool_t *p = mpxs_sv_object_deref(obj, apr_pool_t);
> +        apr_pool_destroy(p);
>      }
>  }
>  
> 
> 

-- 
--------------------------------------------------------------------------------
Philippe M. Chiasson m/gozer\@(apache|cpan|ectoplasm)\.org/ GPG KeyID : 88C3A5A5
http://gozer.ectoplasm.org/     F9BF E0C2 480E 7680 1AE5 3631 CB32 A107 88C3A5A5

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org


Re: [PATCH] Re: segfault ap_save_brigage in the latest 2.0

Posted by Joe Schaefer <jo...@sunstarsys.com>.
"Philippe M. Chiasson" <go...@ectoplasm.org> writes:

> I've tested it hapilly and it is both a simpler implementation
> and gets away with quite an annoying bug, so I'd like to see
> it integrated with a few tweaks.

OK, I've cleaned it up with a few macros as you
suggested.  Patch below...

> - At least one test case for this (check my post 
> http://marc.theaimsgroup.com/?l=apache-modperl-dev&m=109596770111457&w=2

Looks good.  It tests fine, so I tried to include it 
in the patch, but alas:

  $ cvs add pool_lifetime.t
  cvs [server aborted]: "add" requires write access to the repository


Index: xs/APR/Pool/APR__Pool.h
===================================================================
RCS file: /home/cvspublic/modperl-2.0/xs/APR/Pool/APR__Pool.h,v
retrieving revision 1.17
diff -u -r1.17 APR__Pool.h
--- xs/APR/Pool/APR__Pool.h	14 Jul 2004 23:15:01 -0000	1.17
+++ xs/APR/Pool/APR__Pool.h	30 Sep 2004 01:14:04 -0000
@@ -15,10 +15,6 @@
 
 #define MP_APR_POOL_NEW "APR::Pool::new"
 
-typedef struct {
-    SV *sv;
-} mpxs_pool_account_t;
-
 /* XXX: this implementation has a problem with perl ithreads. if a
  * custom pool is allocated, and then a thread is spawned we now have
  * two copies of the pool object, each living in a different perl
@@ -33,6 +29,82 @@
  *   that?) may be we can skip those?
  */
 
+#ifndef MP_SOURCE_SCAN
+#include "apr_optional.h"
+static
+APR_OPTIONAL_FN_TYPE(modperl_interp_unselect) *modperl_opt_interp_unselect;
+#endif
+
+
+#define MP_APR_POOL_SV_HAS_OWNERSHIP(sv) (mg_find(sv, PERL_MAGIC_ext) != NULL)
+
+#define MP_APR_POOL_SV_DROPS_OWNERSHIP(acct) do {               \
+    dTHXa(acct->perl);                                          \
+    mg_free(acct->sv);                                          \
+    SvIVX(acct->sv) = 0;                                        \
+    if (modperl_opt_interp_unselect && acct->interp) {          \
+        /* this will decrement the interp refcnt until          \
+         * there are no more references, in which case          \
+         * the interpreter will be putback into the mip         \
+         */                                                     \
+        (void)modperl_opt_interp_unselect(acct->interp);        \
+    }                                                           \
+} while (0)
+
+
+#ifdef USE_ITHREADS
+
+typedef struct {
+    SV *sv;
+    PerlInterpreter *perl;
+    modperl_interp_t *interp;
+} mpxs_pool_account_t;
+
+
+#define MP_APR_POOL_SV_TAKES_OWNERSHIP(SV, P) do {              \
+    mpxs_pool_account_t *acct = apr_palloc(P, sizeof *acct);    \
+    acct->sv = SV;                                              \
+    acct->perl = aTHX;                                          \
+    SvIVX(SV) = PTR2IV(P);                                      \
+                                                                \
+    sv_magic(SV, Nullsv, PERL_MAGIC_ext,                        \
+             MP_APR_POOL_NEW, sizeof(MP_APR_POOL_NEW));         \
+                                                                \
+    apr_pool_cleanup_register(P, (void *)acct,                  \
+                              mpxs_apr_pool_cleanup,            \
+                              apr_pool_cleanup_null);           \
+                                                                \
+    /* make sure interpreter is not putback into the mip        \
+     * until this cleanup has run.                              \
+     */                                                         \
+    if ((acct->interp = MP_THX_INTERP_GET(aTHX))) {             \
+        acct->interp->refcnt++;                                 \
+    }                                                           \
+} while (0)
+
+#else
+
+typedef struct {
+    SV *sv;
+} mpxs_pool_account_t;
+
+
+#define MP_APR_POOL_SV_TAKES_OWNERSHIP(SV, P) do {              \
+    mpxs_pool_account_t *acct = apr_palloc(P, sizeof *acct);    \
+    acct->sv = SV;                                              \
+    SvIVX(SV) = PTR2IV(P);                                      \
+                                                                \
+    sv_magic(SV, Nullsv, PERL_MAGIC_ext,                        \
+              MP_APR_POOL_NEW, sizeof(MP_APR_POOL_NEW));        \
+                                                                \
+    apr_pool_cleanup_register(P, (void *)acct,                  \
+                              mpxs_apr_pool_cleanup,            \
+                              apr_pool_cleanup_null);           \
+} while (0)
+
+#endif
+
+
 /* XXX: should we make it a new global tracing category
  * MOD_PERL_TRACE=p for tracing pool management? */
 #define MP_POOL_TRACE_DO 0
@@ -50,26 +122,8 @@
 static MP_INLINE apr_status_t
 mpxs_apr_pool_cleanup(void *cleanup_data)
 {
-    mpxs_pool_account_t *data;
-    apr_pool_userdata_get((void **)&data, MP_APR_POOL_NEW,
-                          (apr_pool_t *)cleanup_data);
-    if (!(data && data->sv)) {
-        /* if there is no data, there is nothing to unset */
-        MP_POOL_TRACE(MP_FUNC, "this pool seems to be destroyed already");
-    }
-    else {
-        MP_POOL_TRACE(MP_FUNC,
-                      "pool 0x%lx contains a valid sv 0x%lx, invalidating it",
-                      (unsigned long)data->sv, (unsigned long)cleanup_data);
-
-        /* invalidate all Perl objects referencing this sv */
-        SvIVX(data->sv) = 0;
-
-        /* invalidate the reference stored in the pool */
-        data->sv = NULL;
-        /* data->sv will go away by itself when all objects will go away */
-    }
-
+    mpxs_pool_account_t *acct = cleanup_data;
+    MP_APR_POOL_SV_DROPS_OWNERSHIP(acct);
     return APR_SUCCESS;
 }
 
@@ -116,9 +170,6 @@
      * mess, trying to destroy an already destroyed pool or even worse
      * a pool allocate in the place of the old one.
      */
-    apr_pool_cleanup_register(child_pool, (void *)child_pool,
-                              mpxs_apr_pool_cleanup,
-                              apr_pool_cleanup_null);
 #if APR_POOL_DEBUG
     /* child <-> parent <-> ... <-> top ancestry traversal */
     {
@@ -139,17 +190,13 @@
 #endif
 
     {
-        mpxs_pool_account_t *data =
-            (mpxs_pool_account_t *)apr_pcalloc(child_pool, sizeof(*data));
-
         SV *rv = sv_setref_pv(NEWSV(0, 0), "APR::Pool", (void*)child_pool);
+        SV *sv = SvRV(rv);
 
-        data->sv = SvRV(rv);
+        MP_APR_POOL_SV_TAKES_OWNERSHIP(sv, child_pool);
 
         MP_POOL_TRACE(MP_FUNC, "sub-pool p: 0x%lx, sv: 0x%lx, rv: 0x%lx",
-                      (unsigned long)child_pool, data->sv, rv);
-
-        apr_pool_userdata_set(data, MP_APR_POOL_NEW, NULL, child_pool);
+                      (unsigned long)child_pool, sv, rv);
 
         return rv;
     }
@@ -158,10 +205,9 @@
 static MP_INLINE void mpxs_APR__Pool_clear(pTHX_ SV *obj)
 {
     apr_pool_t *p = mp_xs_sv2_APR__Pool(obj);
-    mpxs_pool_account_t *data;
+    SV *sv = SvRV(obj);
 
-    apr_pool_userdata_get((void **)&data, MP_APR_POOL_NEW, p);
-    if (!(data && data->sv)) {
+    if (!MP_APR_POOL_SV_HAS_OWNERSHIP(sv)) {
         MP_POOL_TRACE(MP_FUNC, "parent pool (0x%lx) is a core pool",
                       (unsigned long)p);
         apr_pool_clear(p);
@@ -171,20 +217,15 @@
     MP_POOL_TRACE(MP_FUNC,
                   "parent pool (0x%lx) is a custom pool, sv 0x%lx",
                   (unsigned long)p,
-                  (unsigned long)data->sv);
+                  (unsigned long)sv);
 
     apr_pool_clear(p);
 
-    /* apr_pool_clear removes all the user data, so we need to restore
+    /* apr_pool_clear removes all the cleanups, so we need to restore
      * it. Since clear triggers mpxs_apr_pool_cleanup call, our
      * object's guts get nuked too, so we need to restore them too */
 
-    /* this is sv_setref_pv, but for an existing object */
-    sv_setiv(newSVrv(obj, "APR::Pool"), PTR2IV((void*)p));
-    data->sv = SvRV(obj);
-
-    /* reinstall the user data */
-    apr_pool_userdata_set(data, MP_APR_POOL_NEW, NULL, p);
+    MP_APR_POOL_SV_TAKES_OWNERSHIP(sv, p);
 }
 
 
@@ -203,11 +244,6 @@
  * @param data   internal storage
  */
 
-#ifndef MP_SOURCE_SCAN
-#include "apr_optional.h"
-static
-APR_OPTIONAL_FN_TYPE(modperl_interp_unselect) *modperl_opt_interp_unselect;
-#endif
 
 static apr_status_t mpxs_cleanup_run(void *data)
 {
@@ -294,30 +330,7 @@
     apr_pool_t *parent_pool = apr_pool_parent_get(child_pool);
 
     if (parent_pool) {
-        /* ideally this should be done by mp_xs_APR__Pool_2obj. Though
-         * since most of the time we don't use custom pools, we don't
-         * want the overhead of reading and writing pool's userdata in
-         * the general case. therefore we do it here and in
-         * mpxs_apr_pool_create. Though if there are any other
-         * functions, that return perl objects whose guts include a
-         * reference to a custom pool, they must do the ref-counting
-         * as well.
-         */
-        mpxs_pool_account_t *data;
-        apr_pool_userdata_get((void **)&data, MP_APR_POOL_NEW, parent_pool);
-        if (data && data->sv) {
-            MP_POOL_TRACE(MP_FUNC,
-                          "parent pool (0x%lx) is a custom pool, sv 0x%lx",
-                          (unsigned long)parent_pool,
-                          (unsigned long)data->sv);
-
-            return newRV_inc(data->sv);
-        }
-        else {
-            MP_POOL_TRACE(MP_FUNC, "parent pool (0x%lx) is a core pool",
-                          (unsigned long)parent_pool);
-            return SvREFCNT_inc(mp_xs_APR__Pool_2obj(parent_pool));
-        }
+        return SvREFCNT_inc(mp_xs_APR__Pool_2obj(parent_pool));
     }
     else {
         MP_POOL_TRACE(MP_FUNC, "pool (0x%lx) has no parents",
@@ -330,42 +343,14 @@
  * destroy a pool
  * @param obj    an APR::Pool object
  */
+
 static MP_INLINE void mpxs_apr_pool_DESTROY(pTHX_ SV *obj)
 {
-    apr_pool_t *p;
     SV *sv = SvRV(obj);
 
-    /* MP_POOL_TRACE(MP_FUNC, "DESTROY 0x%lx-0x%lx",       */
-    /*              (unsigned long)obj,(unsigned long)sv); */
-    /* do_sv_dump(0, Perl_debug_log, obj, 0, 4, FALSE, 0); */
-
-    p = mpxs_sv_object_deref(obj, apr_pool_t);
-    if (!p) {
-        /* non-custom pool */
-        MP_POOL_TRACE(MP_FUNC, "skip apr_pool_destroy: not a custom pool");
-        return;
-    }
-
-    if (sv && SvOK(sv)) {
-        mpxs_pool_account_t *data;
-
-        apr_pool_userdata_get((void **)&data, MP_APR_POOL_NEW, p);
-        if (!(data && data->sv)) {
-            MP_POOL_TRACE(MP_FUNC, "skip apr_pool_destroy: no sv found");
-            return;
-        }
-
-        if (SvREFCNT(sv) == 1) {
-            MP_POOL_TRACE(MP_FUNC, "call apr_pool_destroy: last reference");
-            apr_pool_destroy(p);
-        }
-        else {
-            /* when the pool object dies, sv's ref count decrements
-             * itself automatically */
-            MP_POOL_TRACE(MP_FUNC,
-                          "skip apr_pool_destroy: refcount > 1 (%d)",
-                          SvREFCNT(sv));
-        }
+    if (MP_APR_POOL_SV_HAS_OWNERSHIP(sv)) {
+        apr_pool_t *p = mpxs_sv_object_deref(obj, apr_pool_t);
+        apr_pool_destroy(p);
     }
 }
 


-- 
Joe Schaefer


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org


Re: [PATCH] Re: segfault ap_save_brigage in the latest 2.0

Posted by "Philippe M. Chiasson" <go...@ectoplasm.org>.

Joe Schaefer wrote:
> "Philippe M. Chiasson" <go...@ectoplasm.org> writes:
> 
> 
>>Forgot to mention I want to test this patch and look
>>thru it carefully before it goes in.
> 
> 
> Thanks Phillippe!  Keep in mind I threw it together rather
> hastily, so if you still like it after testing,

I've tested it hapilly and it is both a simpler implementation
and gets away with quite an annoying bug, so I'd like to see
it integrated with a few tweaks.

> I'll gladly 
> clean it up a bit (sync the comments and a the missing 
> #ifdef USE_ITHREADS).

Yes, a few notes on that patch:

- Watch lines > 72 charactres
- sv_magic(sv, Nullsv, PERL_MAGIC_ext, "APR::Pool", sizeof("APR::Pool"));
   - Probably make it a macro since it's twice in the code
   - "APR::Pool" should be in it's own #define
- #ifdef USE_ITHREADS where needed
- At least one test case for this (check my post http://marc.theaimsgroup.com/?l=apache-modperl-dev&m=109596770111457&w=2)

-- 
--------------------------------------------------------------------------------
Philippe M. Chiasson m/gozer\@(apache|cpan|ectoplasm)\.org/ GPG KeyID : 88C3A5A5
http://gozer.ectoplasm.org/     F9BF E0C2 480E 7680 1AE5 3631 CB32 A107 88C3A5A5

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org


Re: [PATCH] Re: segfault ap_save_brigage in the latest 2.0

Posted by Joe Schaefer <jo...@sunstarsys.com>.
"Philippe M. Chiasson" <go...@ectoplasm.org> writes:

> Forgot to mention I want to test this patch and look
> thru it carefully before it goes in.

Thanks Phillippe!  Keep in mind I threw it together rather
hastily, so if you still like it after testing, I'll gladly 
clean it up a bit (sync the comments and a the missing 
#ifdef USE_ITHREADS).

-- 
Joe Schaefer


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org


Re: [PATCH] Re: segfault ap_save_brigage in the latest 2.0

Posted by "Philippe M. Chiasson" <go...@ectoplasm.org>.
Forgot to mention I want to test this patch and look thru it carefully
before it goes in. Won't have time to get to it today, but I'll get around
it tomorrow.

Joe Schaefer wrote:
> ? config.nice
> ? pool.patch
> ? t/core.21302
> Index: xs/APR/Pool/APR__Pool.h
> ===================================================================
> RCS file: /home/cvspublic/modperl-2.0/xs/APR/Pool/APR__Pool.h,v
> retrieving revision 1.17
> diff -u -r1.17 APR__Pool.h
> --- xs/APR/Pool/APR__Pool.h	14 Jul 2004 23:15:01 -0000	1.17
> +++ xs/APR/Pool/APR__Pool.h	28 Sep 2004 21:32:32 -0000
> @@ -17,6 +17,7 @@
>  
>  typedef struct {
>      SV *sv;
> +    PerlInterpreter *perl;
>  } mpxs_pool_account_t;
>  
>  /* XXX: this implementation has a problem with perl ithreads. if a
> @@ -50,26 +51,10 @@
>  static MP_INLINE apr_status_t
>  mpxs_apr_pool_cleanup(void *cleanup_data)
>  {
> -    mpxs_pool_account_t *data;
> -    apr_pool_userdata_get((void **)&data, MP_APR_POOL_NEW,
> -                          (apr_pool_t *)cleanup_data);
> -    if (!(data && data->sv)) {
> -        /* if there is no data, there is nothing to unset */
> -        MP_POOL_TRACE(MP_FUNC, "this pool seems to be destroyed already");
> -    }
> -    else {
> -        MP_POOL_TRACE(MP_FUNC,
> -                      "pool 0x%lx contains a valid sv 0x%lx, invalidating it",
> -                      (unsigned long)data->sv, (unsigned long)cleanup_data);
> -
> -        /* invalidate all Perl objects referencing this sv */
> -        SvIVX(data->sv) = 0;
> -
> -        /* invalidate the reference stored in the pool */
> -        data->sv = NULL;
> -        /* data->sv will go away by itself when all objects will go away */
> -    }
> -
> +    mpxs_pool_account_t *acct = cleanup_data;
> +    dTHXa(acct->perl);
> +    mg_free(acct->sv);
> +    SvIVX(acct->sv) = 0;
>      return APR_SUCCESS;
>  }
>  
> @@ -116,9 +101,6 @@
>       * mess, trying to destroy an already destroyed pool or even worse
>       * a pool allocate in the place of the old one.
>       */
> -    apr_pool_cleanup_register(child_pool, (void *)child_pool,
> -                              mpxs_apr_pool_cleanup,
> -                              apr_pool_cleanup_null);
>  #if APR_POOL_DEBUG
>      /* child <-> parent <-> ... <-> top ancestry traversal */
>      {
> @@ -139,17 +121,22 @@
>  #endif
>  
>      {
> -        mpxs_pool_account_t *data =
> -            (mpxs_pool_account_t *)apr_pcalloc(child_pool, sizeof(*data));
> -
>          SV *rv = sv_setref_pv(NEWSV(0, 0), "APR::Pool", (void*)child_pool);
> +        SV *sv = SvRV(rv);
> +        mpxs_pool_account_t *acct = apr_palloc(child_pool, sizeof *acct);
>  
> -        data->sv = SvRV(rv);
> +        acct->sv = sv;
> +        acct->perl = aTHX;
> +
> +        sv_magic(sv, Nullsv, PERL_MAGIC_ext, "APR::Pool", sizeof("APR::Pool"));
>  
> -        MP_POOL_TRACE(MP_FUNC, "sub-pool p: 0x%lx, sv: 0x%lx, rv: 0x%lx",
> -                      (unsigned long)child_pool, data->sv, rv);
>  
> -        apr_pool_userdata_set(data, MP_APR_POOL_NEW, NULL, child_pool);
> +        apr_pool_cleanup_register(child_pool, (void *)acct,
> +                                  mpxs_apr_pool_cleanup,
> +                                  apr_pool_cleanup_null);
> +
> +        MP_POOL_TRACE(MP_FUNC, "sub-pool p: 0x%lx, sv: 0x%lx, rv: 0x%lx",
> +                      (unsigned long)child_pool, sv, rv);
>  
>          return rv;
>      }
> @@ -158,10 +145,10 @@
>  static MP_INLINE void mpxs_APR__Pool_clear(pTHX_ SV *obj)
>  {
>      apr_pool_t *p = mp_xs_sv2_APR__Pool(obj);
> -    mpxs_pool_account_t *data;
> +    SV *sv = SvRV(obj);
> +    mpxs_pool_account_t *acct;
>  
> -    apr_pool_userdata_get((void **)&data, MP_APR_POOL_NEW, p);
> -    if (!(data && data->sv)) {
> +    if (mg_find(sv, PERL_MAGIC_ext) == NULL) {
>          MP_POOL_TRACE(MP_FUNC, "parent pool (0x%lx) is a core pool",
>                        (unsigned long)p);
>          apr_pool_clear(p);
> @@ -171,20 +158,24 @@
>      MP_POOL_TRACE(MP_FUNC,
>                    "parent pool (0x%lx) is a custom pool, sv 0x%lx",
>                    (unsigned long)p,
> -                  (unsigned long)data->sv);
> +                  (unsigned long)sv);
>  
>      apr_pool_clear(p);
>  
> -    /* apr_pool_clear removes all the user data, so we need to restore
> +    /* apr_pool_clear removes all the cleanup, so we need to restore
>       * it. Since clear triggers mpxs_apr_pool_cleanup call, our
>       * object's guts get nuked too, so we need to restore them too */
>  
>      /* this is sv_setref_pv, but for an existing object */
> -    sv_setiv(newSVrv(obj, "APR::Pool"), PTR2IV((void*)p));
> -    data->sv = SvRV(obj);
> +    sv_magic(sv, Nullsv, PERL_MAGIC_ext, "APR::Pool", sizeof("APR::Pool"));
> +    SvIVX(sv) = (IV)p;
> +    acct = apr_palloc(p, sizeof *acct);
> +    acct->sv = sv;
> +    acct->perl = aTHX;
>  
> -    /* reinstall the user data */
> -    apr_pool_userdata_set(data, MP_APR_POOL_NEW, NULL, p);
> +    apr_pool_cleanup_register(p, (void *)acct,
> +                              mpxs_apr_pool_cleanup,
> +                              apr_pool_cleanup_null);
>  }
>  
>  
> @@ -294,30 +285,7 @@
>      apr_pool_t *parent_pool = apr_pool_parent_get(child_pool);
>  
>      if (parent_pool) {
> -        /* ideally this should be done by mp_xs_APR__Pool_2obj. Though
> -         * since most of the time we don't use custom pools, we don't
> -         * want the overhead of reading and writing pool's userdata in
> -         * the general case. therefore we do it here and in
> -         * mpxs_apr_pool_create. Though if there are any other
> -         * functions, that return perl objects whose guts include a
> -         * reference to a custom pool, they must do the ref-counting
> -         * as well.
> -         */
> -        mpxs_pool_account_t *data;
> -        apr_pool_userdata_get((void **)&data, MP_APR_POOL_NEW, parent_pool);
> -        if (data && data->sv) {
> -            MP_POOL_TRACE(MP_FUNC,
> -                          "parent pool (0x%lx) is a custom pool, sv 0x%lx",
> -                          (unsigned long)parent_pool,
> -                          (unsigned long)data->sv);
> -
> -            return newRV_inc(data->sv);
> -        }
> -        else {
> -            MP_POOL_TRACE(MP_FUNC, "parent pool (0x%lx) is a core pool",
> -                          (unsigned long)parent_pool);
> -            return SvREFCNT_inc(mp_xs_APR__Pool_2obj(parent_pool));
> -        }
> +        return SvREFCNT_inc(mp_xs_APR__Pool_2obj(parent_pool));
>      }
>      else {
>          MP_POOL_TRACE(MP_FUNC, "pool (0x%lx) has no parents",
> @@ -335,11 +303,18 @@
>      apr_pool_t *p;
>      SV *sv = SvRV(obj);
>  
> +    p = mpxs_sv_object_deref(obj, apr_pool_t);
> +
> +    if (mg_find(sv, PERL_MAGIC_ext))
> +        apr_pool_destroy(p);
> +
> +#if 0
> +
>      /* MP_POOL_TRACE(MP_FUNC, "DESTROY 0x%lx-0x%lx",       */
>      /*              (unsigned long)obj,(unsigned long)sv); */
>      /* do_sv_dump(0, Perl_debug_log, obj, 0, 4, FALSE, 0); */
>  
> -    p = mpxs_sv_object_deref(obj, apr_pool_t);
> +
>      if (!p) {
>          /* non-custom pool */
>          MP_POOL_TRACE(MP_FUNC, "skip apr_pool_destroy: not a custom pool");
> @@ -367,5 +342,7 @@
>                            SvREFCNT(sv));
>          }
>      }
> +
> +#endif
>  }
>  
> 
> 
> 
> 
> 
> ------------------------------------------------------------------------
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
> For additional commands, e-mail: dev-help@perl.apache.org

-- 
--------------------------------------------------------------------------------
Philippe M. Chiasson m/gozer\@(apache|cpan|ectoplasm)\.org/ GPG KeyID : 88C3A5A5
http://gozer.ectoplasm.org/     F9BF E0C2 480E 7680 1AE5 3631 CB32 A107 88C3A5A5

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@perl.apache.org
For additional commands, e-mail: dev-help@perl.apache.org