http://www.perlmonks.org?node_id=665353

fenLisesi has asked for the wisdom of the Perl Monks concerning the following question:

Greetings, wise ones -- humbled, as always, in your presence. I have come to seek your blessing on an apache remedy that I concocted.

In my attempts to get my Class::DBI webapp to graze on the plains of Redmond, I have found with grief that it reliably causes Apache2 to crash and burn whenever I try to run Apache2 with more threads than one, brought down by a swarm of flame-arrows, shot by the many threads. The typical dying words of the app include "Free to wrong pool" and "Attempt to free non-existent shared string", finger-written with its own blood, along with the address of Clone::clone in the Class::DBI source.

I replaced Clone::clone in Class/DBI.pm with Storable::dclone and there is no problem now, though a quick benchmark seems to indicate that the application has slowed down. Using the latest version of Clone or sundry versions of Apache2 had not helped. I believe all the perls that I tried had been built from ActiveState sources--I did not try Strawberry or other gcc-compiled perls.

As a fish out of water in Win32 land (though only a frog out of water elsewhere), I need to call upon Win32-experienced monks here. Is Clone inherently bad with multiple-threads of mod_perl2 on Win32, or could it be amenable to a fix by using this compiler instead of that, or downloading the whole combo from such and such repo etc?

How about Storable::dclone replacing Clone::clone? I have not had a chance to run extensive tests yet, but I hope I wasn't too optimistic when I assumed that the two were interchangeble.

Update: The relevant Apache directive is ThreadsPerChild. Having ThreadsPerChild N in httpd.conf with N greater than unity and stress-testing the app (slight stress, really) with apache ab or even by just quickly click-click-clicking for a few seconds on a link that leads to the Clone::clone line in Class/DBI.pm getting executed causes a crash. The webapp itself does not try to use threads.

Update: Class::DBI maintainers inform me that Storable::dclone and Clone::clone are not interchangable. As an example, they say that Storable::dclone cannot clone closures, which are created, for example, to implement triggers.

Replies are listed 'Best First'.
Re: Class::DBI explodes on mod_perl/Win32 due to Clone (!Win32)
by tye (Sage) on Jan 31, 2008 at 16:49 UTC

    This doesn't sound like a Win32 problem.

    Perl isn't thread safe. Perl expects each interpretter and all of its bits to only be run by one thread. And each thread gets its own memory pool. For efficiency, which memory pool to use is determined by what the current thread is. Something is using the wrong pool or creating Perl data items in one thread and then using them in another.

    Clone::clone() is written in XS and XS so very often makes something that is much, much more fragile than something written in plain Perl. It appears that Clone::clone() has no use for the extreme measure of using XS other than "speed!".

    Storable::dclone() is also written in XS but appears to have taken extra steps to handle Perl threads.

    So the speed difference you are seeing (which you didn't bother to describe at all which leads me to guess "not much") may just be the cost of handling threads correctly.

    Compare Storable.xs to Clone.xs and you might be able to improve Clone to handle threads and then re-run your benchmarks.

    Since using Storable::dclone() works, it would appear that Apache2 knows how to compartmentalize Perl interpretters to just one thread each. So it might also work to tweak how Apache2 is built to tell the embedded Perl code that it doesn't care about threads. I wouldn't be too surprised to find that the Apache group hadn't considered using no-threads Perl in a multi-threaded environment. But doing so might cause Clone::clone() to work and might also make the embedded perls run just a bit faster to boot.

    - tye        

Re: Class::DBI explodes on mod_perl/Win32 due to Clone
by bsb (Priest) on Apr 15, 2008 at 07:18 UTC

    Thanks for this. I got a similar explosion on Win32 using fork (pseudo-fork) and fixed it as you suggest by switching to Storable::dclone. The bug could be replicated, but depended strangely on input data and other interactions. It also required lots of work to get an error message. Initially it crashed with a Windows crash dialog and nothing on STDERR. Nasty bug.

    The error, for the sake of frustrated searchers is:

    Attempt to free non-existent shared string '°ÿ2♦', Perl interpreter: 0x4377f9c at C:/Perl/site/lib/Class/DBI.pm line 1032 +.
Re: Class::DBI explodes on mod_perl/Win32 due to Clone
by GeneralElektrix (Acolyte) on Oct 03, 2012 at 19:39 UTC
    Hi,

    I need to share how I solved a similar problem with Package::Stash. Active Perl 5.10.1 Win32, mod_perl 2.0.4. It's a webapp using Template::Toolkit to render the user interface. I have the same "Free to wrong pool" message in Apache's error log.

    For example: Free to wrong pool 2248d88 not 2264038 at X:/Path_to_Perl_site_lib/Package/Stash.pm line 40.. Each one triggered an Apache restart like this: [notice] Parent: child process exited with status 255 -- Restarting.

    After a lot of research on Google and reading obscure posts about how Apache, mod_perl and XS manage threads on Win32, I went to Stash.pm and noticed it chooses between a Pure Perl and an XS implementation around line 24:

    for my $impl ('XS', 'PP') { if (eval "require Package::Stash::$impl; 1;") { $IMPLEMENTATION = $impl; last; } else { $err .= $@; } }

    I simply switched 'XS' and 'PP' around in this for loop and now it chooses the Pure Perl implementation first. Problem solved. I restarted Apache and the error log don't show the "Free to wrong pool" message anymore.

    Thanks to the monks who reported this problem here and helped me solve a similar issue!

      Could you please provide more information about this issue? The authors would like to have this fixed, but more details are needed. Corresponding RT ticket #81861
        More information? The only information I didn't give is the source code for my application. I could share some if necessary. Please tell me what more you'd like to have and I will see what I can do.