Preventing changes to a module's variables in mod_perl

Discussion in 'Perl Misc' started by max@maxgraphic.com, Sep 14, 2006.

  1. Guest

    I have a module that exists as a central data store, returning simple
    scalars or references to larger structures. All of its data is stored
    in a big hash, and I use AUTOLOAD to return the requested value.

    The problem is that, with mod_perl, if the script that uses the module
    changes the data (which with auto-vivication is pretty easy), the data
    is changed for all subsequent scripts using that module run by that
    particular apache child, which leads to the usual hair-pulling
    intermittent bugs that mod_perl users historically puzzle over.

    I've looked at a couple locking options, but the problem is that the
    data can be arbitrarily deep references (which seems to rule out
    Hash::Util). I might have MyModule->foo->{bar}{$baz}, and if $baz isn't
    a valid key, it gets auto-vivified and there goes my weekend.

    Is there a way I can prevent these changes from happening? And without
    a huge performance penalty?

    Thanks.
    , Sep 14, 2006
    #1
    1. Advertising

  2. Ted Zlatanov Guest

    On 14 Sep 2006, wrote:

    > I have a module that exists as a central data store, returning simple
    > scalars or references to larger structures. All of its data is stored
    > in a big hash, and I use AUTOLOAD to return the requested value.
    >
    > The problem is that, with mod_perl, if the script that uses the module
    > changes the data (which with auto-vivication is pretty easy), the data
    > is changed for all subsequent scripts using that module run by that
    > particular apache child, which leads to the usual hair-pulling
    > intermittent bugs that mod_perl users historically puzzle over.
    >
    > I've looked at a couple locking options, but the problem is that the
    > data can be arbitrarily deep references (which seems to rule out
    > Hash::Util). I might have MyModule->foo->{bar}{$baz}, and if $baz isn't
    > a valid key, it gets auto-vivified and there goes my weekend.


    Can you return a tied hash where you control each operation on the
    hash (retaining the syntax you have) to the effect you want? There
    may even be a CPAN module that does what you want, though I'm not
    aware of it.

    Ted
    Ted Zlatanov, Sep 14, 2006
    #2
    1. Advertising

  3. wrote:

    > I have a module that exists as a central data store, returning simple
    > scalars or references to larger structures. All of its data is stored
    > in a big hash, and I use AUTOLOAD to return the requested value.
    >
    > The problem is that, with mod_perl, if the script that uses the module
    > changes the data (which with auto-vivication is pretty easy), the data
    > is changed for all subsequent scripts using that module run by that
    > particular apache child, which leads to the usual hair-pulling
    > intermittent bugs that mod_perl users historically puzzle over.
    >
    > I've looked at a couple locking options, but the problem is that the
    > data can be arbitrarily deep references (which seems to rule out
    > Hash::Util).


    The Readonly module claims to recursively follow deep structures (by
    default).

    Is there a reason you can't simply make the central data store readonly?
    Brian McCauley, Sep 15, 2006
    #3
  4. Guest

    Brian McCauley wrote:
    > wrote:
    >
    > > I have a module that exists as a central data store, returning simple
    > > scalars or references to larger structures. All of its data is stored
    > > in a big hash, and I use AUTOLOAD to return the requested value.
    > >
    > > The problem is that, with mod_perl, if the script that uses the module
    > > changes the data (which with auto-vivication is pretty easy), the data
    > > is changed for all subsequent scripts using that module run by that
    > > particular apache child, which leads to the usual hair-pulling
    > > intermittent bugs that mod_perl users historically puzzle over.
    > >
    > > I've looked at a couple locking options, but the problem is that the
    > > data can be arbitrarily deep references (which seems to rule out
    > > Hash::Util).

    >
    > The Readonly module claims to recursively follow deep structures (by
    > default).
    >
    > Is there a reason you can't simply make the central data store readonly?


    Thanks. I had tried using Storable's dclone to return a copy, which
    worked but was about a hundred times slower than just returning a
    reference. Readonly seems to only be about four times slower.

    Is there a way to get Readonly to warn instead of die when a
    modification attempt is made?
    , Sep 15, 2006
    #4
  5. wrote:

    > Is there a way to get Readonly to warn instead of die when a
    > modification attempt is made?


    There's no such feature at the moment but it would be no biggie to add
    if you wanted to. Just change the croaks() to carps().
    Brian McCauley, Sep 15, 2006
    #5
  6. Guest

    Brian McCauley wrote:
    > wrote:
    >
    > > Is there a way to get Readonly to warn instead of die when a
    > > modification attempt is made?

    >
    > There's no such feature at the moment but it would be no biggie to add
    > if you wanted to. Just change the croaks() to carps().


    Seemingly better still, Readonly uses its own croak wrapper, so adding

    sub Readonly::croak { warn $_[0]; }

    to my module seems to do the trick.

    Thanks again for your help.
    , Sep 15, 2006
    #6
  7. wrote:
    > Brian McCauley wrote:
    > > wrote:
    > >
    > > > Is there a way to get Readonly to warn instead of die when a
    > > > modification attempt is made?

    > >
    > > There's no such feature at the moment but it would be no biggie to add
    > > if you wanted to. Just change the croaks() to carps().

    >
    > Seemingly better still, Readonly uses its own croak wrapper, so adding
    >
    > sub Readonly::croak { warn $_[0]; }
    >
    > to my module seems to do the trick.


    You'd probably get more informative errors with

    sub Readonly::croak {
    require Carp;
    goto &Carp::carp;
    }

    The problem with this approach is it breaks any other uses of Readonly
    that are going on in other modules that anyone who happens to use your
    module is also using.
    Brian McCauley, Sep 15, 2006
    #7
  8. -berlin.de Guest

    Brian McCauley <> wrote in comp.lang.perl.misc:
    >
    > wrote:
    > > Brian McCauley wrote:
    > > > wrote:
    > > >
    > > > > Is there a way to get Readonly to warn instead of die when a
    > > > > modification attempt is made?
    > > >
    > > > There's no such feature at the moment but it would be no biggie to add
    > > > if you wanted to. Just change the croaks() to carps().

    > >
    > > Seemingly better still, Readonly uses its own croak wrapper, so adding
    > >
    > > sub Readonly::croak { warn $_[0]; }
    > >
    > > to my module seems to do the trick.

    >
    > You'd probably get more informative errors with
    >
    > sub Readonly::croak {
    > require Carp;
    > goto &Carp::carp;
    > }
    >
    > The problem with this approach is it breaks any other uses of Readonly
    > that are going on in other modules that anyone who happens to use your
    > module is also using.


    The substitution can be localized to a block or file:

    local *Readonly::croak = sub {
    require Carp;
    goto &Carp::carp;
    };

    Anno
    -berlin.de, Sep 18, 2006
    #8
  9. -berlin.de wrote:
    > Brian McCauley <> wrote in comp.lang.perl.misc:
    > >
    > > You'd probably get more informative errors with
    > >
    > > sub Readonly::croak {
    > > require Carp;
    > > goto &Carp::carp;
    > > }
    > >
    > > The problem with this approach is it breaks any other uses of Readonly
    > > that are going on in other modules that anyone who happens to use your
    > > module is also using.

    >
    > The substitution can be localized to a block or file:
    >
    > local *Readonly::croak = sub {
    > require Carp;
    > goto &Carp::carp;
    > };


    No! local() is dynamically scoped not lexical. Changes made with
    local() are _not_ localized to a block or file but to a stack frame
    (and subframes thereof).

    Anyhow, even if it where lexical it would help the OP since he wants to
    control the behaviour of complex data structures returned by his
    modules when code outwith his control tries to modify them.
    Brian McCauley, Sep 19, 2006
    #9
  10. -berlin.de Guest

    Brian McCauley <> wrote in comp.lang.perl.misc:
    >
    > -berlin.de wrote:
    > > Brian McCauley <> wrote in comp.lang.perl.misc:
    > > >
    > > > You'd probably get more informative errors with
    > > >
    > > > sub Readonly::croak {
    > > > require Carp;
    > > > goto &Carp::carp;
    > > > }
    > > >
    > > > The problem with this approach is it breaks any other uses of Readonly
    > > > that are going on in other modules that anyone who happens to use your
    > > > module is also using.

    > >
    > > The substitution can be localized to a block or file:
    > >
    > > local *Readonly::croak = sub {
    > > require Carp;
    > > goto &Carp::carp;
    > > };

    >
    > No! local() is dynamically scoped not lexical. Changes made with
    > local() are _not_ localized to a block or file but to a stack frame
    > (and subframes thereof).


    Yes, of course. That means, once control has left the block the change
    is reverted. In simple cases that may be good enough.

    > Anyhow, even if it where lexical it would help the OP since he wants to
    > control the behaviour of complex data structures returned by his
    > modules when code outwith his control tries to modify them.


    Hmm... tie() comes to mind then.

    I admit I've lost context of the thread, so I'm not sure if that big
    gun is warranted. Maybe a certain module named Tie::OneOff could be
    useful... :)

    Anno
    -berlin.de, Sep 19, 2006
    #10
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. javelin
    Replies:
    5
    Views:
    170
    Anthony Jones
    Dec 19, 2006
  2. Gunnar Hjalmarsson

    Global variables in mod_perl

    Gunnar Hjalmarsson, May 17, 2004, in forum: Perl Misc
    Replies:
    6
    Views:
    201
    Gunnar Hjalmarsson
    May 18, 2004
  3. nicc777
    Replies:
    2
    Views:
    155
    Richard Gration
    Jul 13, 2005
  4. Replies:
    2
    Views:
    438
    Big and Blue
    Jan 25, 2006
  5. tszming
    Replies:
    2
    Views:
    165
    Peter Makholm
    Oct 13, 2008
Loading...

Share This Page