develooper Front page | perl.perl5.porters | Postings from January 2007

Re: New release ? ([perl #40965])

Thread Previous | Thread Next
From:
Jan Dubois
Date:
January 16, 2007 18:58
Subject:
Re: New release ? ([perl #40965])
Message ID:
p72rq2laqrfuvc317oqfdgee2j5kgnc2s2@4ax.com
On Mon, 15 Jan 2007 15:14:30 +0000, Dave Mitchell <davem@iabyn.com>
wrote:

>Change 29827 by davem@davem-pigeon on 2007/01/15 14:16:53
>
>        extend threads 'veto cleanup' to perl_free and system stuff
>
>
>This is the one I would like feedback on. (the patch is included below)
>
>Although the veto mechanism stops the main interpreter from each pool
>being freed, it doesn't stop global cleanup. In particular, in the UNIX
>case, main() calls PERL_SYS_TERM, which destroys all the global mutexes
>like PL_op_mutex. If a detached thread happens to try to access this mutex
>at around the same time that the main thread is exiting, Bad things happen.
>
>I've fixed this by introducing a new (true) global variable,
>PL_veto_cleanup, which is set in perl_destruct the first time
>PL_threadhook returns true, and once set, is never unset. This flag is then
>used by perl_free(), and the UNIX versions of PERL_SYS_TERM and perl_fini()
>to skip any global cleanup.
>
>An issue with this is that it's only fixed for the UNIX case; I haven't
>dared mess with the win32 version (or any other version for that matter).
>Also, I don't know whether there's a better approach.
>
>Also, the original veto mechanism is per interpreter pool; I have now
>extended it to be global in scope. This embedding business isn't my area
>of expertise, so I'd like other eyes to look at it.
>
>To expand on this:
>
>A program (eg mod_perl in Apache) is capable of creating several
>interpreters. Each interpreter can individually do a 'use threads'; in
>which case that interpreter will become a 'main interpreter' for the pool
>of threads created from that original interpreter. All threads from each
>pool would share global mutexes like PL_op_mutex, but each pool would
>have its own pool-wide mutexes like create_destruct_mutex, which are
>allocated by that pool's main thread.
>
>The old veto model meant that if any threads in one pool outlived
>their main thread, then that one main interpreter wasn't freed. However,
>after all main threads had exited, and the program itself was exiting,
>then PERL_SYS_TERM and perl_fini() would still get called to free the global
>mutexes and pthread keys respectively, regardless of whether there were any
>detached threads still running.
>
>The new change vetos  this global cleanup. I don't know whether that has
>any bad ramifications.

I think this is fine.

As far as embedding is concerned, I personally have given up on
executing PERL_SYS_TERM in embedding applications.  You are either
terminating the process anyways, so you can leave the cleanup to the OS.
Or you may be in an environment where a different component may also be
embedding Perl interpreters, and may fail when you call PERL_SYS_TERM.

Of course the same issue exists for PERL_SYS_INIT, but this is really
just a race condition, and re-initializing the mutex variables is
"mostly benign".  If another component was holding the mutex, then
releasing it will silently fail, and afterwards everyone is using the
new mutex.  The window for actual failure is pretty small.  You can only
close it if you control *all* parts that may be embedding Perl.

I think these environments are relatively rare though; the ones I've
been working on are COM and .NET components that encapsulate Perl
interpreters.  In those cases you simply don't "own" the embedding
environment, and there is no way to know if you should or shouldn't call
PERL_SYS_INIT/TERM.

For additional fun consider the case where 2 components try to embed 2
different versions of Perl in the same process. This does not work
because you would end up with 2 different values for PL_thr_key, and XS
modules will simply not know which one to use because they use this key
to find the interpreter.  So you have to make sure you can work with the
interpreter already mapped into the process...

This is not a theoretical scenario; there are companies that sell COM
and .NET components implemented using Perl (using PerlCtrl and PerlNET
from the ActiveState Perl Dev Kit), and I needed to be able to deal with
the fact that _their_ customers can use multiple components that have
been built using different versions of Perl within a single application.
Or that they may try to use those components from a another Perl
instance via Win32::OLE.

Anyways, the purpose of the "rant" was to show why I do care that
individual pools of interpreters clean up properly after themselves, but
that for global cleanup I don't see a viable solution that would help
with the scenarios I'm dealing with.  I think of PERL_SYS_TERM just as a
debugging tool to make it easier to see if Perl is leaking anything at
all.

Cheers,
-Jan

PS: I just remembered one other PERL_SYS_TERM() annoyance: You can only
call PERL_SYS_TERM() if you called perl_construct() at least once.
PERL_SYS_INIT() doesn't provide enough initialization to call
PERL_SYS_TERM() safely.

Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About