Hello,
I posted a couple of weeks ago and since I did not get any answers, I am trying again but this time with complete test code that anyone can run on their own machine.
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):
<IfModule mpm_worker_module>
StartServers 1
MinSpareThreads 5
ThreadsPerChild 20
MaxRequestsPerChild 0
ServerLimit 1
PerlInterpMax 1
</IfModule>
To the site configuration also add:
<Location /testSharing>
SetHandler perl-script
PerlResponseHandler U2D::TestSharing
</Location>
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 at all since the fruits array is shared and we are always running in the same process. 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
SSSSSSSSOOOOOLLLLLLLVVVVVVEEEEEEEDDDDDDD:
The problem is that the shared variable needs to be loaded BEFORE the threads are created. This is done by creating a startup.pl file and adding PerlRequire startup.pl to the VirtualHost config. The entire startup.pl file looks like this:
use strict;
use warnings FATAL => 'all';
require threads;
"threads"->import();
use U2D::TestSharing ();
1;
Once I did this and added the sleep(1); to the handler as I discussed below then everything worked like a charm. The fruits array was created only once and shared by the other threads. All threads locked and waited just as I would expect. If you don't believe me, tail -f testSharing.log and watch the beauty unfold before your own eyes!
LOAD YOUR SHARED VARIABLES IN THE STARTUP.PL FILE BEFORE USING THEM IN THE HANDLERS!!!