Sharing variable in threaded mpm not working as expected

Sharing variable in threaded mpm not working as expected

am 02.08.2011 09:06:59 von Pawel Herman

Hello,

I have read all the related documentation (at least those that I
found) and I still cannot understand why the little program I wrote
below does not share the variable as I would expect. The log file
that I created clearly shows that we are running in a single process.
Some threads see the shared variable and others do not. I even
reduced the number of pooled interpreters to one and still no luck.

You will need an Apache running in Ubuntu 11.04 with mod_perl 2.0.
Then add this code:

package U2D::TestSharing;

use strict;

use Apache2::Const -compile => qw(OK);
use threads;
use threads::shared;
use APR::OS ();
use Time::Format qw(%time);
use Apache2::RequestRec;

our @fruits :shared = ();

sub handler {
my $r = shift;
$r->content_type('application/json');

{
logTestMessage('Waiting for lock.');
lock(@fruits);
logTestMessage('Acquired lock.');
if(scalar(@fruits) == 0) {
logTestMessage('Initializing fruits.');
push(@fruits,'apple');
push(@fruits,'banana');
push(@fruits,'peach');
}
logTestMessage('Releasing lock.');
}

my $message = "I like to eat ".join(', ',@fruits).".";

print $message;
logTestMessage($message);

return Apache2::Const::OK;
}

sub logTestMessage {
my $message = shift;
my $tid = APR::OS::current_thread_id();
if(open(FILE,'>>/testSharing.log')) {
print FILE $time{'dd-mm-yyyy hh:mm:ss:mmm'}.' '.$$.'-'.$tid.':
+ '.$message."\n";
close(FILE);
} else { print $!."\n"; }
}

1;

Add the following lines to apache2.conf (or uncomment the specified lines):


StartServers 1
MinSpareThreads 5
ThreadsPerChild 20
MaxRequestsPerChild 0
ServerLimit 1
PerlInterpMax 1


To the site configuration also add:


SetHandler perl-script
PerlResponseHandler U2D::TestSharing


Then write a little JavaScript that loops 100 times and calls
http://localhost/testSharing and check the log file. Here I am posting
the beginning of the log on my machine:

02-08-2011 07:42:27:552 2669-3063479152: Waiting for lock.
02-08-2011 07:42:27:565 2669-3063479152: Acquired lock.
02-08-2011 07:42:27:566 2669-3063479152: Initializing fruits.
02-08-2011 07:42:27:566 2669-3063479152: Releasing lock.
02-08-2011 07:42:27:566 2669-3063479152: I like to eat apple, banana, peach.
02-08-2011 07:42:27:578 2669-3063479152: Waiting for lock.
02-08-2011 07:42:27:578 2669-3063479152: Acquired lock.
02-08-2011 07:42:27:578 2669-3063479152: Releasing lock.
02-08-2011 07:42:27:578 2669-3063479152: I like to eat apple, banana, peach.
02-08-2011 07:42:27:578 2669-3021515632: Waiting for lock.
02-08-2011 07:42:27:579 2669-3021515632: Acquired lock.
02-08-2011 07:42:27:579 2669-3021515632: Releasing lock.
02-08-2011 07:42:27:579 2669-3021515632: I like to eat apple, banana, peach.
02-08-2011 07:42:27:574 2669-3046693744: Waiting for lock.
02-08-2011 07:42:27:582 2669-3046693744: Acquired lock.
02-08-2011 07:42:27:582 2669-3046693744: Initializing fruits.
02-08-2011 07:42:27:582 2669-3046693744: Releasing lock.
02-08-2011 07:42:27:582 2669-3046693744: I like to eat apple, banana, peach.
02-08-2011 07:42:27:583 2669-3063479152: Waiting for lock.
02-08-2011 07:42:27:583 2669-3063479152: Acquired lock.
02-08-2011 07:42:27:583 2669-3063479152: Releasing lock.
02-08-2011 07:42:27:583 2669-3063479152: I like to eat apple, banana, peach.
02-08-2011 07:42:27:588 2669-3063479152: Waiting for lock.
02-08-2011 07:42:27:588 2669-3063479152: Acquired lock.
02-08-2011 07:42:27:588 2669-3063479152: Releasing lock.
02-08-2011 07:42:27:588 2669-3063479152: I like to eat apple, banana, peach.
02-08-2011 07:42:27:581 2669-3055086448: Waiting for lock.
02-08-2011 07:42:27:589 2669-3055086448: Acquired lock.
02-08-2011 07:42:27:589 2669-3055086448: Initializing fruits.
02-08-2011 07:42:27:589 2669-3055086448: Releasing lock.
02-08-2011 07:42:27:589 2669-3055086448: I like to eat apple, banana, peach.
02-08-2011 07:42:27:582 2669-3038301040: Waiting for lock.
02-08-2011 07:42:27:589 2669-3038301040: Acquired lock.
02-08-2011 07:42:27:589 2669-3038301040: Initializing fruits.
02-08-2011 07:42:27:589 2669-3038301040: Releasing lock.
02-08-2011 07:42:27:590 2669-3038301040: I like to eat apple, banana, peach.
02-08-2011 07:42:27:588 2669-3013122928: Waiting for lock.
02-08-2011 07:42:27:594 2669-3013122928: Acquired lock.
02-08-2011 07:42:27:594 2669-3013122928: Initializing fruits.
02-08-2011 07:42:27:594 2669-3013122928: Releasing lock.
02-08-2011 07:42:27:594 2669-3013122928: I like to eat apple, banana, peach.

The fruits array is initialized multiple times. This is not expected
since the fruits array is shared and we are always running in the same
process. (Note: Thread 2669-3063479152 populates the array initially.
Then thread 2669-3021515632 uses it but thread 2669-3046693744 creates
the array again. Just as a side note: as I was testing this, I also
ran into situations where multiple threads acquired the lock
simultaneously. The expected behavior is that only one thread can
lock at a time.) Can anyone tell me why this code does not work?

Thank you for your help in advance. I hope someone can shed some light
on this problem that I am having for weeks now.

Sincerely,

Pawel

Re: Sharing variable in threaded mpm not working as expected

am 02.08.2011 20:24:46 von Fred Moyer

I haven't used the worker mpm, but it looks like you might want to
preload your handler in the httpd parent process. You can do with a
startup.pl file. It looks like each thread is initializing a copy of
@fruits, which is probably happening at thread creation.

However, your current setup will block according to the mod_perl docs,
so you may want to revisit your approach.

If all running interpreters are in use, mod_perl will clone new
interpreters to handle the request, up until this number of
interpreters is reached. when PerlInterpMax is reached, mod_perl will
block (via COND_WAIT()) until one becomes available (signaled via
COND_SIGNAL()).

On Tue, Aug 2, 2011 at 12:06 AM, Pawel Herman wrote=
:
> Hello,
>
> I have read all the related documentation (at least those that I
> found) and I still cannot understand why the little program I wrote
> below does not share the variable as I would expect. =A0The log file
> that I created clearly shows that we are running in a single process.
> Some threads see the shared variable and others do not. =A0I even
> reduced the number of pooled interpreters to one and still no luck.
>
> You will need an Apache running in Ubuntu 11.04 with mod_perl 2.0.
> Then add this code:
>
> package U2D::TestSharing;
>
> use strict;
>
> use Apache2::Const -compile =3D> qw(OK);
> use threads;
> use threads::shared;
> use APR::OS ();
> use Time::Format qw(%time);
> use Apache2::RequestRec;
>
> our @fruits :shared =3D ();
>
> sub handler {
> =A0 =A0my $r =3D shift;
> =A0 =A0$r->content_type('application/json');
>
> =A0 =A0{
> =A0 =A0 =A0 =A0logTestMessage('Waiting for lock.');
> =A0 =A0 =A0 =A0lock(@fruits);
> =A0 =A0 =A0 =A0logTestMessage('Acquired lock.');
> =A0 =A0 =A0 =A0if(scalar(@fruits) == 0) {
> =A0 =A0 =A0 =A0 =A0 =A0logTestMessage('Initializing fruits.');
> =A0 =A0 =A0 =A0 =A0 =A0push(@fruits,'apple');
> =A0 =A0 =A0 =A0 =A0 =A0push(@fruits,'banana');
> =A0 =A0 =A0 =A0 =A0 =A0push(@fruits,'peach');
> =A0 =A0 =A0 =A0}
> =A0 =A0 =A0 =A0logTestMessage('Releasing lock.');
> =A0 =A0}
>
> =A0 =A0my $message =3D "I like to eat ".join(', ',@fruits).".";
>
> =A0 =A0print $message;
> =A0 =A0logTestMessage($message);
>
> =A0 =A0return Apache2::Const::OK;
> }
>
> sub logTestMessage {
> =A0 =A0my $message =3D shift;
> =A0 =A0my $tid =3D APR::OS::current_thread_id();
> =A0 =A0if(open(FILE,'>>/testSharing.log')) {
> =A0 =A0 =A0 =A0print FILE $time{'dd-mm-yyyy hh:mm:ss:mmm'}.' '.$$.'-'.$ti=
d.':
> + '.$message."\n";
> =A0 =A0 =A0 =A0close(FILE);
> =A0 =A0} else { print $!."\n"; }
> }
>
> 1;
>
> Add the following lines to apache2.conf (or uncomment the specified lines=
):
>
>
> =A0 =A0StartServers =A0 =A0 =A0 =A0 =A01
> =A0 =A0MinSpareThreads =A0 =A0 =A0 5
> =A0 =A0ThreadsPerChild =A0 =A0 =A020
> =A0 =A0MaxRequestsPerChild =A0 0
> =A0 =A0ServerLimit =A0 =A0 =A0 =A0 =A0 1
> =A0 =A0PerlInterpMax =A0 =A0 =A0 =A0 1
>

>
> To the site configuration also add:
>
>
> =A0 =A0SetHandler perl-script
> =A0 =A0PerlResponseHandler U2D::TestSharing
>

>
> Then write a little JavaScript that loops 100 times and calls
> http://localhost/testSharing and check the log file. Here I am posting
> the beginning of the log on my machine:
>
> 02-08-2011 07:42:27:552 2669-3063479152: Waiting for lock.
> 02-08-2011 07:42:27:565 2669-3063479152: Acquired lock.
> 02-08-2011 07:42:27:566 2669-3063479152: Initializing fruits.
> 02-08-2011 07:42:27:566 2669-3063479152: Releasing lock.
> 02-08-2011 07:42:27:566 2669-3063479152: I like to eat apple, banana, pea=
ch.
> 02-08-2011 07:42:27:578 2669-3063479152: Waiting for lock.
> 02-08-2011 07:42:27:578 2669-3063479152: Acquired lock.
> 02-08-2011 07:42:27:578 2669-3063479152: Releasing lock.
> 02-08-2011 07:42:27:578 2669-3063479152: I like to eat apple, banana, pea=
ch.
> 02-08-2011 07:42:27:578 2669-3021515632: Waiting for lock.
> 02-08-2011 07:42:27:579 2669-3021515632: Acquired lock.
> 02-08-2011 07:42:27:579 2669-3021515632: Releasing lock.
> 02-08-2011 07:42:27:579 2669-3021515632: I like to eat apple, banana, pea=
ch.
> 02-08-2011 07:42:27:574 2669-3046693744: Waiting for lock.
> 02-08-2011 07:42:27:582 2669-3046693744: Acquired lock.
> 02-08-2011 07:42:27:582 2669-3046693744: Initializing fruits.
> 02-08-2011 07:42:27:582 2669-3046693744: Releasing lock.
> 02-08-2011 07:42:27:582 2669-3046693744: I like to eat apple, banana, pea=
ch.
> 02-08-2011 07:42:27:583 2669-3063479152: Waiting for lock.
> 02-08-2011 07:42:27:583 2669-3063479152: Acquired lock.
> 02-08-2011 07:42:27:583 2669-3063479152: Releasing lock.
> 02-08-2011 07:42:27:583 2669-3063479152: I like to eat apple, banana, pea=
ch.
> 02-08-2011 07:42:27:588 2669-3063479152: Waiting for lock.
> 02-08-2011 07:42:27:588 2669-3063479152: Acquired lock.
> 02-08-2011 07:42:27:588 2669-3063479152: Releasing lock.
> 02-08-2011 07:42:27:588 2669-3063479152: I like to eat apple, banana, pea=
ch.
> 02-08-2011 07:42:27:581 2669-3055086448: Waiting for lock.
> 02-08-2011 07:42:27:589 2669-3055086448: Acquired lock.
> 02-08-2011 07:42:27:589 2669-3055086448: Initializing fruits.
> 02-08-2011 07:42:27:589 2669-3055086448: Releasing lock.
> 02-08-2011 07:42:27:589 2669-3055086448: I like to eat apple, banana, pea=
ch.
> 02-08-2011 07:42:27:582 2669-3038301040: Waiting for lock.
> 02-08-2011 07:42:27:589 2669-3038301040: Acquired lock.
> 02-08-2011 07:42:27:589 2669-3038301040: Initializing fruits.
> 02-08-2011 07:42:27:589 2669-3038301040: Releasing lock.
> 02-08-2011 07:42:27:590 2669-3038301040: I like to eat apple, banana, pea=
ch.
> 02-08-2011 07:42:27:588 2669-3013122928: Waiting for lock.
> 02-08-2011 07:42:27:594 2669-3013122928: Acquired lock.
> 02-08-2011 07:42:27:594 2669-3013122928: Initializing fruits.
> 02-08-2011 07:42:27:594 2669-3013122928: Releasing lock.
> 02-08-2011 07:42:27:594 2669-3013122928: I like to eat apple, banana, pea=
ch.
>
> The fruits array is initialized multiple times. This is not expected
> since the fruits array is shared and we are always running in the same
> process. (Note: Thread 2669-3063479152 populates the array initially.
> Then thread 2669-3021515632 uses it but thread 2669-3046693744 creates
> the array again. =A0Just as a side note: as I was testing this, I also
> ran into situations where multiple threads acquired the lock
> simultaneously. =A0The expected behavior is that only one thread can
> lock at a time.) =A0Can anyone tell me why this code does not work?
>
> Thank you for your help in advance. I hope someone can shed some light
> on this problem that I am having for weeks now.
>
> Sincerely,
>
> Pawel
>

Re: Sharing variable in threaded mpm not working as expected

am 02.08.2011 20:42:42 von Pawel Herman

Hello Fred,

I already tried the startup.pl file. That didn't help but I can try again.

The text you quoted from the docs is familiar to me. That is why I
set PerlInterpMax to 1 in my configuration (I want it to block for
testing and understanding purposes and intellectual exercise). I
initially thought that since PerlInterpMax defaults to 5 that the
shared variable was not shared among the interpreters (which does not
make sense because that is the point of sharing, that the variable is
visible to all threads in the process). Even if I only have one
interpreter, the variable is not shared. As you can see in my log,
some threads see the shared fruits array and others do not. Why?

Is there a way to print the id or address of the interpreter so that I
can be sure that only one is being used?

In case anyone is wondering, I also removed PerlModule Apache2::Reload
a while ago so that is not the problem either.

Sincerely,
Pawel

On Tue, Aug 2, 2011 at 8:24 PM, Fred Moyer wrote:
> I haven't used the worker mpm, but it looks like you might want to
> preload your handler in the httpd parent process. =A0You can do with a
> startup.pl file. =A0It looks like each thread is initializing a copy of
> @fruits, which is probably happening at thread creation.
>
> However, your current setup will block according to the mod_perl docs,
> so you may want to revisit your approach.
>
> If all running interpreters are in use, mod_perl will clone new
> interpreters to handle the request, up until this number of
> interpreters is reached. when PerlInterpMax is reached, mod_perl will
> block (via COND_WAIT()) until one becomes available (signaled via
> COND_SIGNAL()).
>
> On Tue, Aug 2, 2011 at 12:06 AM, Pawel Herman wro=
te:
>> Hello,
>>
>> I have read all the related documentation (at least those that I
>> found) and I still cannot understand why the little program I wrote
>> below does not share the variable as I would expect. =A0The log file
>> that I created clearly shows that we are running in a single process.
>> Some threads see the shared variable and others do not. =A0I even
>> reduced the number of pooled interpreters to one and still no luck.
>>
>> You will need an Apache running in Ubuntu 11.04 with mod_perl 2.0.
>> Then add this code:
>>
>> package U2D::TestSharing;
>>
>> use strict;
>>
>> use Apache2::Const -compile =3D> qw(OK);
>> use threads;
>> use threads::shared;
>> use APR::OS ();
>> use Time::Format qw(%time);
>> use Apache2::RequestRec;
>>
>> our @fruits :shared =3D ();
>>
>> sub handler {
>> =A0 =A0my $r =3D shift;
>> =A0 =A0$r->content_type('application/json');
>>
>> =A0 =A0{
>> =A0 =A0 =A0 =A0logTestMessage('Waiting for lock.');
>> =A0 =A0 =A0 =A0lock(@fruits);
>> =A0 =A0 =A0 =A0logTestMessage('Acquired lock.');
>> =A0 =A0 =A0 =A0if(scalar(@fruits) == 0) {
>> =A0 =A0 =A0 =A0 =A0 =A0logTestMessage('Initializing fruits.');
>> =A0 =A0 =A0 =A0 =A0 =A0push(@fruits,'apple');
>> =A0 =A0 =A0 =A0 =A0 =A0push(@fruits,'banana');
>> =A0 =A0 =A0 =A0 =A0 =A0push(@fruits,'peach');
>> =A0 =A0 =A0 =A0}
>> =A0 =A0 =A0 =A0logTestMessage('Releasing lock.');
>> =A0 =A0}
>>
>> =A0 =A0my $message =3D "I like to eat ".join(', ',@fruits).".";
>>
>> =A0 =A0print $message;
>> =A0 =A0logTestMessage($message);
>>
>> =A0 =A0return Apache2::Const::OK;
>> }
>>
>> sub logTestMessage {
>> =A0 =A0my $message =3D shift;
>> =A0 =A0my $tid =3D APR::OS::current_thread_id();
>> =A0 =A0if(open(FILE,'>>/testSharing.log')) {
>> =A0 =A0 =A0 =A0print FILE $time{'dd-mm-yyyy hh:mm:ss:mmm'}.' '.$$.'-'.$t=
id.':
>> + '.$message."\n";
>> =A0 =A0 =A0 =A0close(FILE);
>> =A0 =A0} else { print $!."\n"; }
>> }
>>
>> 1;
>>
>> Add the following lines to apache2.conf (or uncomment the specified line=
s):
>>
>>
>> =A0 =A0StartServers =A0 =A0 =A0 =A0 =A01
>> =A0 =A0MinSpareThreads =A0 =A0 =A0 5
>> =A0 =A0ThreadsPerChild =A0 =A0 =A020
>> =A0 =A0MaxRequestsPerChild =A0 0
>> =A0 =A0ServerLimit =A0 =A0 =A0 =A0 =A0 1
>> =A0 =A0PerlInterpMax =A0 =A0 =A0 =A0 1
>>

>>
>> To the site configuration also add:
>>
>>
>> =A0 =A0SetHandler perl-script
>> =A0 =A0PerlResponseHandler U2D::TestSharing
>>

>>
>> Then write a little JavaScript that loops 100 times and calls
>> http://localhost/testSharing and check the log file. Here I am posting
>> the beginning of the log on my machine:
>>
>> 02-08-2011 07:42:27:552 2669-3063479152: Waiting for lock.
>> 02-08-2011 07:42:27:565 2669-3063479152: Acquired lock.
>> 02-08-2011 07:42:27:566 2669-3063479152: Initializing fruits.
>> 02-08-2011 07:42:27:566 2669-3063479152: Releasing lock.
>> 02-08-2011 07:42:27:566 2669-3063479152: I like to eat apple, banana, pe=
ach.
>> 02-08-2011 07:42:27:578 2669-3063479152: Waiting for lock.
>> 02-08-2011 07:42:27:578 2669-3063479152: Acquired lock.
>> 02-08-2011 07:42:27:578 2669-3063479152: Releasing lock.
>> 02-08-2011 07:42:27:578 2669-3063479152: I like to eat apple, banana, pe=
ach.
>> 02-08-2011 07:42:27:578 2669-3021515632: Waiting for lock.
>> 02-08-2011 07:42:27:579 2669-3021515632: Acquired lock.
>> 02-08-2011 07:42:27:579 2669-3021515632: Releasing lock.
>> 02-08-2011 07:42:27:579 2669-3021515632: I like to eat apple, banana, pe=
ach.
>> 02-08-2011 07:42:27:574 2669-3046693744: Waiting for lock.
>> 02-08-2011 07:42:27:582 2669-3046693744: Acquired lock.
>> 02-08-2011 07:42:27:582 2669-3046693744: Initializing fruits.
>> 02-08-2011 07:42:27:582 2669-3046693744: Releasing lock.
>> 02-08-2011 07:42:27:582 2669-3046693744: I like to eat apple, banana, pe=
ach.
>> 02-08-2011 07:42:27:583 2669-3063479152: Waiting for lock.
>> 02-08-2011 07:42:27:583 2669-3063479152: Acquired lock.
>> 02-08-2011 07:42:27:583 2669-3063479152: Releasing lock.
>> 02-08-2011 07:42:27:583 2669-3063479152: I like to eat apple, banana, pe=
ach.
>> 02-08-2011 07:42:27:588 2669-3063479152: Waiting for lock.
>> 02-08-2011 07:42:27:588 2669-3063479152: Acquired lock.
>> 02-08-2011 07:42:27:588 2669-3063479152: Releasing lock.
>> 02-08-2011 07:42:27:588 2669-3063479152: I like to eat apple, banana, pe=
ach.
>> 02-08-2011 07:42:27:581 2669-3055086448: Waiting for lock.
>> 02-08-2011 07:42:27:589 2669-3055086448: Acquired lock.
>> 02-08-2011 07:42:27:589 2669-3055086448: Initializing fruits.
>> 02-08-2011 07:42:27:589 2669-3055086448: Releasing lock.
>> 02-08-2011 07:42:27:589 2669-3055086448: I like to eat apple, banana, pe=
ach.
>> 02-08-2011 07:42:27:582 2669-3038301040: Waiting for lock.
>> 02-08-2011 07:42:27:589 2669-3038301040: Acquired lock.
>> 02-08-2011 07:42:27:589 2669-3038301040: Initializing fruits.
>> 02-08-2011 07:42:27:589 2669-3038301040: Releasing lock.
>> 02-08-2011 07:42:27:590 2669-3038301040: I like to eat apple, banana, pe=
ach.
>> 02-08-2011 07:42:27:588 2669-3013122928: Waiting for lock.
>> 02-08-2011 07:42:27:594 2669-3013122928: Acquired lock.
>> 02-08-2011 07:42:27:594 2669-3013122928: Initializing fruits.
>> 02-08-2011 07:42:27:594 2669-3013122928: Releasing lock.
>> 02-08-2011 07:42:27:594 2669-3013122928: I like to eat apple, banana, pe=
ach.
>>
>> The fruits array is initialized multiple times. This is not expected
>> since the fruits array is shared and we are always running in the same
>> process. (Note: Thread 2669-3063479152 populates the array initially.
>> Then thread 2669-3021515632 uses it but thread 2669-3046693744 creates
>> the array again. =A0Just as a side note: as I was testing this, I also
>> ran into situations where multiple threads acquired the lock
>> simultaneously. =A0The expected behavior is that only one thread can
>> lock at a time.) =A0Can anyone tell me why this code does not work?
>>
>> Thank you for your help in advance. I hope someone can shed some light
>> on this problem that I am having for weeks now.
>>
>> Sincerely,
>>
>> Pawel
>>
>

Re: Sharing variable in threaded mpm not working as expected

am 02.08.2011 20:55:51 von torsten.foertsch

On Tuesday, 02 August 2011 20:24:46 Fred Moyer wrote:
> I haven't used the worker mpm, but it looks like you might want to
> preload your handler in the httpd parent process.

Unlikely that that will help. threads::shared works by creating a=20
separate perl interpreter to keep the shared values. That interpreter=20
does not execute any program. It simply serves as shared storage. When a=20
variable is then marked as shared it is assigned magic to have the normal=20
accessor methods use the storage in the other interpreter. So, no matter=20
when the variable or the interpreter executing a program is created=20
shared variables are always fetched from the special storage interpreter.

The special storage interpreter is a global variable at C-level.

t/response/TestPerl/ithreads.pm in the modperl test suite exercises=20
shared variables. I'd take this as a starting point. First, I'd create a=20
simple shared scalar as a global counter. If that works (which I think it=20
does) the rest is how to use threads::shared correctly.

As for your code I think you could try to push shared apples like this

push(@fruits,share('apple'));

Perhaps even

push(@fruits,share(do {my $x=3D'apple'}));

Torsten Förtsch

=2D-=20
Need professional modperl support? Hire me! (http://foertsch.name)

Like fantasy? http://kabatinte.net

Re: Sharing variable in threaded mpm not working as expected

am 05.08.2011 07:29:33 von Pawel Herman

Hello Torsten,

I tried your suggestions push(@fruits,share('apple')); and
push(@fruits,share(do {my $x=3D'apple'})); but both did not work because
share can only take references, arrays, or hashes as input. I tried
similar variations but no luck. The fruits array is still initialized
multiple times. I even created the global counter like you suggested:

my $counter :shared =3D 0;

and then in the handler method:

{
logTestMessage('Waiting for lock.');
lock($counter);
logTestMessage('Acquired lock.');
if($counter == 0) {
logTestMessage('Increasing counter.');
$counter++;
}
logTestMessage('Releasing lock.');
}

but even then, the counter is increased multiple times. As far as
populating the fruits array goes, I believe after reading
http://perldoc.perl.org/threads/shared.html that my approach is
correct. It specifically says in the Bugs and Limitations section
that one first declares a variable shared and then populates it.
Since 'apple', 'banana', and 'peach' are scalars, they do not have to
be explicitly shared.

You pointed me to a module in the modperl test suite. I downloaded
modperl from http://perl.apache.org/download/index.html but there is
no t/response/TestPerl/ithreads.pm. I also searched for the string
'threads::shared' in all directories but no luck. Where did you get
this pm?

Sincerely,
Pawel

2011/8/2 Torsten Förtsch :
> On Tuesday, 02 August 2011 20:24:46 Fred Moyer wrote:
>> I haven't used the worker mpm, but it looks like you might want to
>> preload your handler in the httpd parent process.
>
> Unlikely that that will help. threads::shared works by creating a
> separate perl interpreter to keep the shared values. That interpreter
> does not execute any program. It simply serves as shared storage. When a
> variable is then marked as shared it is assigned magic to have the normal
> accessor methods use the storage in the other interpreter. So, no matter
> when the variable or the interpreter executing a program is created
> shared variables are always fetched from the special storage interpreter.
>
> The special storage interpreter is a global variable at C-level.
>
> t/response/TestPerl/ithreads.pm in the modperl test suite exercises
> shared variables. I'd take this as a starting point. First, I'd create a
> simple shared scalar as a global counter. If that works (which I think it
> does) the rest is how to use threads::shared correctly.
>
> As for your code I think you could try to push shared apples like this
>
> =A0push(@fruits,share('apple'));
>
> Perhaps even
>
> =A0push(@fruits,share(do {my $x=3D'apple'}));
>
> Torsten Förtsch
>
> --
> Need professional modperl support? Hire me! (http://foertsch.name)
>
> Like fantasy? http://kabatinte.net
>

Re: Sharing variable in threaded mpm not working as expected

am 06.08.2011 15:39:00 von Vincent Veyron

Le vendredi 05 août 2011 à 07:29 +0200, Pawel Herman a écrit :

> You pointed me to a module in the modperl test suite. I downloaded
> modperl from http://perl.apache.org/download/index.html but there is
> no t/response/TestPerl/ithreads.pm. I also searched for the string
> 'threads::shared' in all directories but no luck. Where did you get
> this pm?

you need to install Apache::Test

http://httpd.apache.org/test/


--
Vincent Veyron
http://marica.fr/
Logiciel de gestion des sinistres et des contentieux pour le service juridique

Re: Sharing variable in threaded mpm not working as expected

am 09.08.2011 08:34:15 von Pawel Herman

Hello Torsten and Fred,

So I looked at ithreads.pm (found it in an svn repository online
http://svn.apache.org/viewvc/perl/modperl/trunk/t/response/T estPerl/)
and from what I saw, my approach was theoretically the same as in the
test module except that the threads were created after the shared
variable was declared, which in my case was different.=A0 I decided to
investigate Fred's suggestion of preloading my modules in startup.pl
more closely.=A0 I remember doing that once but I guess I was a little
careless because this time it worked. In order to solve my problem, I
created startup.pl with the following code:

use strict;
use warnings FATAL =3D> 'all';

require threads;
"threads"->import();
use U2D::TestSharing ();

1;

Then I added PerlRequire startup.pl to my VirtualHost config and
inserted sleep(1); before the line logTestMessage('Releasing lock.');.
While running tail -f testSharing.log I saw that multiple threads
answered the requests simultaneously and only one initialized the
array. So Fred's suggestion of preloading the module was correct.

Thank you very much for everyone's help. Anyone playing with the
worker mpm in the future should take note:

LOAD YOUR SHARED VARIABLES IN THE STARTUP.PL FILE BEFORE USING THEM IN
THE HANDLERS!!!

Sincerely,
Pawel

2011/8/2 Torsten Förtsch
>
> On Tuesday, 02 August 2011 20:24:46 Fred Moyer wrote:
> > I haven't used the worker mpm, but it looks like you might want to
> > preload your handler in the httpd parent process.
>
> Unlikely that that will help. threads::shared works by creating a
> separate perl interpreter to keep the shared values. That interpreter
> does not execute any program. It simply serves as shared storage. When a
> variable is then marked as shared it is assigned magic to have the normal
> accessor methods use the storage in the other interpreter. So, no matter
> when the variable or the interpreter executing a program is created
> shared variables are always fetched from the special storage interpreter.
>
> The special storage interpreter is a global variable at C-level.
>
> t/response/TestPerl/ithreads.pm in the modperl test suite exercises
> shared variables. I'd take this as a starting point. First, I'd create a
> simple shared scalar as a global counter. If that works (which I think it
> does) the rest is how to use threads::shared correctly.
>
> As for your code I think you could try to push shared apples like this
>
> =A0push(@fruits,share('apple'));
>
> Perhaps even
>
> =A0push(@fruits,share(do {my $x=3D'apple'}));
>
> Torsten Förtsch
>
> --
> Need professional modperl support? Hire me! (http://foertsch.name)
>
> Like fantasy? http://kabatinte.net