Stas Bekman wrote: [...]
First of all we have to separate the objects in two groups: those created by users (1) and those created by Apache/mp2 (2).
(1) things which are completely under user control look easy, for example if you create an APR::Table object, we can clone it by copying the table in the spawned thread. The question is what pool should we use for that purpose? We can't use the pool from the parent thread. Since the parent thread may be killed before the child one (for detached threads). and if it's APR::Pool object itself that needs to be cloned, which pool do we use to clone it? How do we avoid leaks?
Ideas? I'm not sure it's doable at all.
(2) Things are even harder with objects created by Apache/mp2. I mean how in the world are we going to clone things like $r or $c? there are all kind of things attached to those objects, including sockets, etc. and now we suddenly need to free those objects too.
Here I'm even more lost.
I think I've an idea that may work. All that automatic cloning business is really unwanted in the mod_perl environment. I think if we try to empty the cloned objects of the pointer to the C struct, it will render them unusable in the spawned threads, but it'll prevent multiple destruction problem. Next we can try and see if we can properly clone objects, one class at a time.
Unfortunately due to the badly-designed by the perl core CLONE function it's going to be quite a hassle to do even that, as you can see from Example::CLONE. :(
I'll try with APR::Pool first.
Stas, who enjoys talking to himself...
The following seems to make APR::Pool objects "happy" (=nosegfault) under ithread cloning. But it's going to be a pain to do that for each class, since there are more than one entry point. I wish CLONE was implemented differently. Luckily I didn't have to use Scalar::Util, so the code is a bit simpler.
Index: xs/APR/Pool/APR__Pool.h
===================================================================
--- xs/APR/Pool/APR__Pool.h (revision 158003)
+++ xs/APR/Pool/APR__Pool.h (working copy)
@@ -216,6 +216,22 @@
if (parent_pool) {
mpxs_add_pool_magic(rv, parent_pool_obj);
}
+
+ {
+ HV *hv;
+ SV *weak_rv, *sv_key;
+
+ /* $objects{"$$self"} = $self;
+ Scalar::Util::weaken($objects{"$$self"})
+ */
+ hv = get_hv("APR::Pool::CLONE_objects", TRUE);
+ /* use the real object pointer as a unique key */
+ sv_key = newSVpvf("%p", SvIVX(SvRV(rv)));
+ weak_rv = newRV(SvRV(rv));
+ sv_rvweaken(weak_rv); /* ala Scalar::Util::weaken */
+ hv_store_ent(hv, sv_key, weak_rv, FALSE);
+ sv_free(sv_key);
+ } return rv;
}
@@ -369,8 +385,32 @@
SV *sv = SvRV(obj); if (MP_APR_POOL_SV_HAS_OWNERSHIP(sv)) {
+ HV *hv = get_hv("APR::Pool::CLONE_objects", TRUE);
+ SV *sv_key = newSVpvf("%p", SvIVX(SvRV(obj)));
+ /* delete $CLONE_objects{"$$self"}; */
+ hv_delete_ent(hv, sv_key, G_DISCARD, FALSE);
+ sv_free(sv_key);
+
apr_pool_t *p = mpxs_sv_object_deref(obj, apr_pool_t);
apr_pool_destroy(p);
}
}+static void make_hollow(pTHX_ SV *obj)
+{
+ SV *sv = SvRV(obj);
+ /* detach form the C struct and invalidate */
+ SvIVX(sv) = 0;
+ SvIOK_off(sv);
+ mg_free(sv); /* remove any magic */
+}
+
+static MP_INLINE void mpxs_apr_pool_CLONE(pTHX_ SV *class)
+{
+ HE *he;
+ HV *hv = get_hv("APR::Pool::CLONE_objects", TRUE);
+ hv_iterinit(hv);
+ while ((he = hv_iternext(hv))) {
+ make_hollow(aTHX_ hv_iterval(hv, he));
+ }
+}-- __________________________________________________________________ Stas Bekman JAm_pH ------> Just Another mod_perl Hacker http://stason.org/ mod_perl Guide ---> http://perl.apache.org mailto:[EMAIL PROTECTED] http://use.perl.org http://apacheweek.com http://modperlbook.org http://apache.org http://ticketmaster.com
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
