Process coordination in mod_perl under working MPM

I need to do a simple timezone calculation in mod_perl. DateTime is not an option. What I need to do is easy to accomplish by setting $ ENV {TZ} and using localtime and POSIX :: mktime, but under multi-threaded MPM I would need to make sure that only one thread was cheating on the environment at a time. (I'm not interested in other options for using localtime, etc.)

How can I use a mutex or other blocking strategy to serialize (in a sense without marshalling) access to the environment? docs I looked not very well explain how to create a mutex for this use. Maybe there is something that I just don’t understand about how you create mutexes at all.

Update: yes, I know that I need to use Env :: C to install TZ.

+3
source share
3 answers

(repeating what I said at PerlMonks ...)

BEGIN {
    my $mutex;

    sub that {
        $mutex ||= APR::ThreadMutex->new( $r->pool() );
        $mutex->lock();

        $ENV{TZ}= ...;
        ...

        $mutex->unlock();
    }
}

But of course, lock () should happen in c'tor, and unlock () should happen in d'tor, with the exception of one-time hacks.

Update: note that there is a race condition in how $ mutex is initialized in the subroutine (two threads can call this () for the first time almost simultaneously). You will most likely want to initialize $ mutex before creating the (additional) threads, but I am unclear in the details on the “working” Apache MPM and how you easily accomplished this. If there is any code that starts early, simply saying that () from there will destroy the race.

APR:: ThreadMutex:

BEGIN {
    my $mutex;

    sub that {
        my $autoLock= APR::ThreadMutex->autoLock( \$mutex );
        ...
        # Mutex automatically released when $autoLock destroyed
    }
}

, autoLock(), undef, , , $mutex.

+3

- mod_perl 2 % ENV , mod_perl 1. mod_perl 1% ENV , % ENV . mod_perl 2 % ENV , .

, $ENV {TZ} - . Apache2:: Localtime ( Env:: C), MPM, .

mod_perl (src/modules/perl/modperl_env.c) :

/* * XXX: what we do here might change:
 *      - make it optional for %ENV to be tied to r->subprocess_env
 *      - make it possible to modify environ
 *      - we could allow modification of environ if mpm isn't threaded
 *      - we could allow modification of environ if variable isn't a CGI
 *        variable (still could cause problems)
 */
/*
 * problems we are trying to solve:
 *      - environ is shared between threads
 *          + Perl does not serialize access to environ
 *          + even if it did, CGI variables cannot be shared between threads!
 * problems we create by trying to solve above problems:
 *      - a forked process will not inherit the current %ENV
 *      - C libraries might rely on environ, e.g. DBD::Oracle
 */
+3

apache 1.3, . Apache 1.3 , . :

{
    local $ENV{TZ} = whatever_I_need_it_to_be();

    # Do calculations here.
}

local , , , . , . , , .

apache 2 , . , .

If apache 2 uses honest and good true streams, then this is outside my area of ​​detailed knowledge, but I hope another wonderful stackoverflow person can help.

All the best

Paul
+1
source

Source: https://habr.com/ru/post/1697422/


All Articles