Question

I'm trying to make a web server whose requests are farmed out to a set of interpreters hidden behind open2(), based on which 'device' is indicated in the cgi parameters.

The trouble is, I want it multi-threaded but the hash I'm using to try to keep track of the event queue relating to each device doesn't remember the new device created for each request: the server below only prints this sort of thing:

Did not find default-device in (alreadyThere)...

Added default-device with Sun Oct 27 20:43:35 2013 to alreadyThere, default-device
Now... does (alreadyThere, default-device) persist for the next request?

Here is the script:

#!/usr/bin/perl -w
use strict;
use threads;
use threads::shared;
use base qw(Net::Server::HTTP);

our $monkeys = shared_clone({ alreadyThere => { 'a' => 'b' } });

sub process_http_request {
    require CGI;
    my $cgi = CGI->new;
    my $device = $cgi->param('device') || 'default-device';

    print "HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n<pre>";
    unless (exists $monkeys->{$device}) {
        print "Did not find $device in (".join(", ", sort keys %$monkeys).")...\n";
        lock $monkeys;
        unless (exists $monkeys->{$device}) {
            my $t = localtime;
            $monkeys->{$device} = $t;
            print "\nAdded $device with ".$t." to ".join(", ", sort keys %$monkeys);
        } else {
            print "\nSurprise device... ".$device;
        }
    } else {
        print "\nFound device... ".$device;
    }

    print "\nNow... does (".join(", ", sort keys %$monkeys).") persist for the next request?</pre>";
}

__PACKAGE__->run(port => 8080);

It's not the $t bit - that was previously shared_clone({ id => $t }), but I'm darned if I can see why $monkeys never seems to update.

Was it helpful?

Solution

The different requests are served by different processes, not threads.

Net::Server doesn't have a multi-threaded "personality"[1], so you're going to have to use a different sharing mechanism.


Notes:

  1. "in the near future, we would like to add a 'Thread' personality"

OTHER TIPS

Building on Ikegami's answer, I'm trying with this additional code to fake a 'threaded' personality with some success (and some problems with 'open3' misbehaving):

sub default_server_type { 'Single' }

sub loop {
  my $self = shift;
  while( $self->accept ){
    async {
        $self->run_client_connection;
    };
    last if $self->done;
  }
}

a) Is there any reason to use Net::Server::HTTP instead of the higher level and easier to use Plack?
b) I've had to solve a problem not unlike this one recently, and settled on using event-based httpd with AnyEvent (or higher abstraction, Coro). There's Net::Server::Coro if you need a drop-in replacement for your code, or even a plethora of canned AnyEvent-based httpds like Twiggy, Feersum, etc.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top