in reply to Threaded MPM Sharing Variables (this time with complete test code)

After updating the site configuration to
<Location /testSharing> Options -MultiViews SetHandler perl-script PerlResponseHandler U2D::TestSharing </Location>
because apparently MultiViews doesn't work well with the code for updating the logfile.
I'm getting the following output when holding down F5 a few seconds in my browser:
02-08-2011 13:09:40:037 9209-4216514368: Waiting for lock. 02-08-2011 13:09:40:045 9209-4216514368: Acquired lock. 02-08-2011 13:09:40:045 9209-4216514368: Initializing fruits. 02-08-2011 13:09:40:045 9209-4216514368: Releasing lock. 02-08-2011 13:09:40:045 9209-4216514368: I like to eat apple, banana, +peach. 02-08-2011 13:09:40:443 9209-4216514368: Waiting for lock. 02-08-2011 13:09:40:443 9209-4216514368: Acquired lock. 02-08-2011 13:09:40:443 9209-4216514368: Releasing lock. 02-08-2011 13:09:40:443 9209-4216514368: I like to eat apple, banana, +peach. 02-08-2011 13:09:40:941 9209-4216514368: Waiting for lock. 02-08-2011 13:09:40:941 9209-4216514368: Acquired lock. 02-08-2011 13:09:40:942 9209-4216514368: Releasing lock. 02-08-2011 13:09:40:942 9209-4216514368: I like to eat apple, banana, +peach. 02-08-2011 13:09:41:000 9209-4216514368: Waiting for lock. 02-08-2011 13:09:41:001 9209-4216514368: Acquired lock. 02-08-2011 13:09:41:001 9209-4216514368: Releasing lock. 02-08-2011 13:09:41:001 9209-4216514368: I like to eat apple, banana, +peach. 02-08-2011 13:09:41:014 9209-4216514368: Waiting for lock. 02-08-2011 13:09:41:014 9209-4216514368: Acquired lock. 02-08-2011 13:09:41:014 9209-4216514368: Releasing lock. 02-08-2011 13:09:41:014 9209-4216514368: I like to eat apple, banana, +peach. 02-08-2011 13:09:41:062 9209-4216514368: Waiting for lock. 02-08-2011 13:09:41:063 9209-4216514368: Acquired lock. 02-08-2011 13:09:41:063 9209-4216514368: Releasing lock. 02-08-2011 13:09:41:063 9209-4216514368: I like to eat apple, banana, +peach. 02-08-2011 13:09:41:090 9209-4216514368: Waiting for lock. 02-08-2011 13:09:41:090 9209-4216514368: Acquired lock. 02-08-2011 13:09:41:090 9209-4216514368: Releasing lock. 02-08-2011 13:09:41:090 9209-4216514368: I like to eat apple, banana, +peach. 02-08-2011 13:09:41:119 9209-4216514368: Waiting for lock. 02-08-2011 13:09:41:119 9209-4216514368: Acquired lock. 02-08-2011 13:09:41:119 9209-4216514368: Releasing lock. 02-08-2011 13:09:41:120 9209-4216514368: I like to eat apple, banana, +peach. 02-08-2011 13:09:41:146 9209-4216514368: Waiting for lock. 02-08-2011 13:09:41:146 9209-4216514368: Acquired lock. 02-08-2011 13:09:41:146 9209-4216514368: Releasing lock. 02-08-2011 13:09:41:146 9209-4216514368: I like to eat apple, banana, +peach. 02-08-2011 13:09:41:191 9209-4216514368: Waiting for lock. 02-08-2011 13:09:41:192 9209-4216514368: Acquired lock. 02-08-2011 13:09:41:192 9209-4216514368: Releasing lock. 02-08-2011 13:09:41:192 9209-4216514368: I like to eat apple, banana, +peach. 02-08-2011 13:09:41:222 9209-4216514368: Waiting for lock. 02-08-2011 13:09:41:222 9209-4216514368: Acquired lock. 02-08-2011 13:09:41:222 9209-4216514368: Releasing lock. 02-08-2011 13:09:41:222 9209-4216514368: I like to eat apple, banana, +peach. 02-08-2011 13:09:41:253 9209-4216514368: Waiting for lock. 02-08-2011 13:09:41:253 9209-4216514368: Acquired lock. 02-08-2011 13:09:41:253 9209-4216514368: Releasing lock. 02-08-2011 13:09:41:253 9209-4216514368: I like to eat apple, banana, +peach.
That looks reasonably like the result you wanted, so I wonder what's happening on your end that makes things different.
Oh, and I changed your logTestMessage a bit, since / is not a writable location for apache (hence the 'permission denied's I was getting).
sub logTestMessage { my $message = shift; my $tid = APR::OS::current_thread_id(); if(open(FILE,'>>','/var/www/testSharing.log')) { print FILE $time{'dd-mm-yyyy hh:mm:ss:mmm'}.' '.$$.'-'.$tid.': + '.$message."\n"; close(FILE); } else { print "Error opening file: ".$!."\n"; } }

Replies are listed 'Best First'.
Re^2: Threaded MPM Sharing Variables (this time with complete test code)
by Neighbour (Friar) on Aug 02, 2011 at 11:24 UTC
    After a few more attempts at leaning on F5, I am indeed getting multiple "Initializing"-lines in the logfile.
    Then this occurred to me:
    root@myserver:/usr/local/lib/site_perl/U2D# ps aux | grep apa root 9546 0.0 0.3 148856 9920 ? Ss 13:16 0:00 /usr/ +sbin/apache2 -k start www-data 9549 0.0 0.3 173424 9880 ? S 13:16 0:00 /usr/ +sbin/apache2 -k start www-data 9550 0.0 0.3 173424 9860 ? S 13:16 0:00 /usr/ +sbin/apache2 -k start www-data 9551 0.0 0.3 173424 9860 ? S 13:16 0:00 /usr/ +sbin/apache2 -k start www-data 9552 0.0 0.3 173424 9860 ? S 13:16 0:00 /usr/ +sbin/apache2 -k start www-data 9553 0.0 0.3 173424 9860 ? S 13:16 0:00 /usr/ +sbin/apache2 -k start www-data 9618 0.0 0.3 173424 9860 ? S 13:19 0:00 /usr/ +sbin/apache2 -k start root 9723 0.0 0.0 7624 920 pts/0 S+ 13:20 0:00 grep +apa root@myserver:/usr/local/lib/site_perl/U2D# grep Initializing /var/www +/testSharing.log 02-08-2011 13:19:38:736 9549-172922688: Initializing fruits. 02-08-2011 13:19:39:361 9550-172922688: Initializing fruits. 02-08-2011 13:19:39:426 9551-172922688: Initializing fruits. 02-08-2011 13:19:39:457 9552-172922688: Initializing fruits. 02-08-2011 13:19:39:480 9553-172922688: Initializing fruits. 02-08-2011 13:19:39:499 9618-172922688: Initializing fruits.
    Which leads me to think that for each running instance of apache2, the variable will have to be initialized at least once. Or is that too shortsighted?

      Hello Neighbour,

      Here is the javascript code:

      function init() { var options = { type: "POST", url: "testSharing", }; for(var i = 0; i < 100; i++) $.ajax(options); } $(document).ready(init);

      You need to download jQuery so that this code works but you can also create equivalent code that does not use jQuery and that does the same thing. At least you have the idea of what I am doing.

      As far as permissions go:

      sudo chown www-data:www-data /testSharing.log sudo chmod 660 /testSharing.log

      will do the trick.

      In your case, you are running multiple processes, as you can see in your log output (the four digit number before the hyphen after the milliseconds field). In order to force Apache to run as a single process with multiple threads, you need to change the config in apache2.conf by adding/changing:

      <IfModule mpm_worker_module> StartServers 1 MinSpareThreads 5 ThreadsPerChild 20 MaxRequestsPerChild 0 ServerLimit 1 PerlInterpMax 1 </IfModule>

      Also, install the worker mpm by running:

      sudo apt-get install apache2-mpm-worker

      Then, you will only have a single process and multiple threads, as you will clearly see when you run the javascript above and check the log file.

      I hope someone can help me with this problem. Still not clear why multiple instances are initialized.

      Sincerely,

      Pawel

        An even better solution is to add

        sleep(1);

        before the line

        logTestMessage('Releasing lock.');
        Then you can press F5 as much as you want (at least five times).

        Thanks for the javascript-code. I've got the libjs-jquery package installed, but I'm not sure how to use the javascript-code you provided (I'm not a webdev :)). Do I just put it in a .js-file and plop it in /var/www to access it using a browser? (Which only shows the contents, it doesn't run it).

        Switching from apache2-mpm-prefork (needed for php5) to apache2-mpm-worker seems to have reduced the number of running apache2-process to 3 (One owned by root, 2 by www-data).

        Putting files in / is against the filesystem-hierarchy standard (and my personal opinion on where to put files). Though your trick will allow apache2 access to /testSharing.log, this is not the place to put that file. Regardless, I got it to work using /var/www/testSharing.log (as I explained earlier), so that's not really an issue.

        Trying my previous method by holding down F5 for a bit now gets me only one occurrence of 'Initializing'.

        Hello Neighbour,

        For some reason I cannot reply directly to your last message. Here is the html that would run my code:

        <html> <head> <script type="text/javascript" src="http://localhost/jquery-1.6.1.min. +js"></script> <script> function init() { var options = { type: "POST", url: "http://localhost/testSharing", }; for(var i = 0; i < 100; i++) $.ajax(options); } $(document).ready(init); </script> </head> <body> </body> </html>

        This is assuming that you place your jquery source at the root (the file is named jquery-1.6.1.min.js). You can download jquery from http://jquery.com/. I am not sure what the package is that you installed. Javascript files are simple text files with code that you can place directly in your document root.

        Also don't forget to update your apache2.conf file with the <IfModule mpm_worker_module> etc. This will force Apache to process requests in a single process, which you should see when you look at the log file outputted by the handler. There should only be one number in the process ID field.

        Pressing F5 with your finger is simply not fast enough, which is why we need the javascript code to pound the server with several requests simultaneously so that we force it to use at least two threads at the same time. That's why you also need to pay attention to the output in the log file I created. The process ID should be the same (threads::shared cannot share a variable across processes; testing it across multiple process does not make sense). Then, you should see different thread IDs as well. Ideally, there is only one Initializing statement even if several threads access the shared variable. My problem is that I get multiple Initializing statements even when all requests are processed in one process and multiple threads answer. Note that during my testing I had cases where some new threads did not output Initializing... but others did. So it looked to me like the sharing of the variable worked sometimes and other times it did not. I would like to understand why.

        Anyway, I am excited to hear whether you can reproduce my results as well. Don't forget to update apache2.conf and let me know how the javascript works for you.

        Sincerely,

        Pawel

        Remove "http://localhost/" from the URLs in the html code I sent you :).