Perl

NAVIGATION
CATEGORIES
REFERRENCE
LINKS
  • threads module falsely assumes that its BOOT section is executed only once per process

    6 answers - 660 bytes - related search similar search Add To My Delicious Add To My Stumble Upon Add To My Google Mark Add To My Facebook Add To My Digg Add To My Reddit

    This assumption is false if you have an application that embeds multiple
    Perl interpreters and these interpreters in turn use the threads module.
    I've noticed the problem with Perl 5.8.8 and threads 1.31, but a cursory
    look at the latest threads.xs on CPAN shows that the module still assumes
    that all but the very first interpreter are created through the threads
    module.
    give-away of this problem is the initialization of static variables
    in the BT section. Modules doing this are typically not safe for use
    in a multi-interpreter environment where BT can be executed more than
    once.
    Cheers,
    -Jan
  • No.1 | | 735 bytes | |

    Jerry writes:
    Interesting. I think I know how to fix this, but I have no idea how to
    test it. Any suggestions on how to write a test for this?

    You could write an XS module to call perl_alloc(), perl_construct(),
    perl_parse(), etc. to create a second interpreter.

    You can control what the 2nd interpreter does by passing stuff
    in through the argc,argv options to perl_parse(), e.g.

    "-Mthreads::test -eruntests"

    where threads::test is your test module. It exports the runtests()
    function that implements your test suite.

    You don't want to install this module, so disable the "install"
    target in its Makefile.PL (see ext/XS/APItest/Makefile.PL).

    Cheers,
    -Jan
  • No.2 | | 1621 bytes | |

    Thu, 26, 2006 at 11:29:36AM -0700, Jerry D. Hedden wrote:
    I thought the way to fix this was to move all the static
    variables into MY_CXT. However, I couldn't get this to
    work. For example, consider putting just the TID counter
    into MY_CXT:

    typedef struct {
    /* Used by Perl interpreter for thread context switching */
    ithread *context;

    UV tid_counter;
    } my_cxt_t;

    The problem is as follows. Currently threads.xs, by calling MY_CXT_CLNE,
    ensures that the pseudo-static data in

    struct { ithread *thread} my_cxt_t

    is allocated per interpreter, rather than shared between all threads'
    interpreters; while vars like tid_counter need to be shared within each
    pool of interpreters.

    to put it another way, if a C program embeds two perl interpreters, and
    each interpreter runs the following program:

    use threads;
    thread->new() for 15;

    then we should get the following:

    BT: called twice;
    two pools of interpreters;
    within each pool, there is a unique tid_counter, so a total of two
    tid_counters
    Each pool contains 6 threads, each with an associated interpreter, each of
    which has an individual MY_CXT.thread value.

    An "easy" fix for this is to add a new per-interpreter var, PL_ithread say,
    and use this to point to the ithread structure. Then ditch calling
    MY_CXT_CLNE, making the MY_CXT vars per interpreter pool rather than per
    interpreter, then shove tid_counter et al. there.

    That however has the rather large drawback of tying the threads module
    directly to the core.
  • No.3 | | 918 bytes | |

    Dave writes:
    An "easy" fix for this is to add a new per-interpreter var, PL_ithread say,
    and use this to point to the ithread structure. Then ditch calling
    MY_CXT_CLNE, making the MY_CXT vars per interpreter pool rather than per
    interpreter, then shove tid_counter et al. there.

    I don't think you need an "explicit" per-interpreter variable.
    There is nothing that prevents you from using 2 MY_CXT structures in
    the module, one that is per-interpreter (reallocated in CLNE)
    and one that will be global to the pool. The global one would need
    to store its tid in the structure during BT time so that the same
    interpreter can tear it down.

    Well, the MY_CXT macro may not support this directly, but they are
    just syntactic sugar around storing values in the PL_modglobal hash
    to avoid the hash access if you compile without MULTIPLICITY.

    Cheers,
    -Jan
  • No.4 | | 496 bytes | |

    Fri, 27, 2006 at 01:25:39PM -0700, Jan Dubois wrote:
    Well, the MY_CXT macro may not support this directly, but they are
    just syntactic sugar around storing values in the PL_modglobal hash
    to avoid the hash access if you compile without MULTIPLICITY.

    Er, I completely rewrote the MY_CXT* macros a few months ago to make them
    a lot more efficient; they no longer use PL_modglobal, and only provide
    one struct per source file - due to a static var per file (see START_MY_CXT).
  • No.5 | | 1114 bytes | |

    Dave wrote:
    Fri, 27, 2006 at 01:25:39PM -0700, Jan Dubois wrote:
    Well, the MY_CXT macro may not support this directly, but they are
    just syntactic sugar around storing values in the PL_modglobal hash
    to avoid the hash access if you compile without MULTIPLICITY.

    Er, I completely rewrote the MY_CXT* macros a few months ago to make them
    a lot more efficient; they no longer use PL_modglobal, and only provide
    one struct per source file - due to a static var per file (see START_MY_CXT).

    Sorry, I completely forgot about this.

    But anyways, PL_modglobal is still around to store per-interpreter
    module data if one wants to use it.

    Another (better) idea is to have 2 additional fields in the MY_CXT data:
    one that stores the BT tid, and a pointer to the "global to the pool"
    data. That way every thread can access this data through the MY_CXT,
    and the BT thread can then free it when it is being destructed.

    Either way, I think it is very desirable to *not* add additional
    core variables if not absolutely necessary.

    Cheers,
    -Jan
  • No.6 | | 937 bytes | |

    Quoth jdhedden (AT) 1979 (DOT) usna.com:
    Jerry writes:
    Interesting. I think I know how to fix this, but I have
    no idea how to test it. Any suggestions on how to write a
    test for this?

    Jan Dubois wrote:
    You could write an XS module to call perl_alloc(),
    perl_construct(), perl_parse(), etc. to create a second
    interpreter.

    You can control what the 2nd interpreter does by passing
    stuff in through the argc,argv options to perl_parse(),
    e.g.

    "-Mthreads::test -eruntests"

    where threads::test is your test module. It exports the
    runtests() function that implements your test suite.

    I have no idea how to do any of this. Sorry, but it's
    beyond my present knowledge. Is there something that does
    this sort of thing already that I could use as an example?
    would somebody please generate something that I could use
    as a starting point?

    Perl.pm .

    Ben

Re: threads module falsely assumes that its BOOT section is executed only once per process


max 4000 letters.
Your nickname that display:
In order to stop the spam: 6 + 5 =
QUESTION ON "Perl"

EMSDN.COM