Anyone tried to create multitreaded HTTP daemon using SOAP::Lite?
[email protected] ("Maxim Maltchevski")
| Newsgroups | perl.ithreads |
|---|---|
| Message-ID | <[email protected]> |
Hi everyone:
I'm writing a simple HTTP daemon using SOAP::Lite. I would like to handle
each client request in its own thread to improve the response time. I'm
working with the Active State Perl 5.8.0, build 806 on a Win2K Pro machine.
The following code blocks in the $conn->get_request() call until it times
out (sub process_request). If I uncomment "sleep 1" line in the parent loop,
then the threads are created and executed one after another as expected but
this, of course, defeats the whole purpose of using threads. I can't share
my $conn variable which holds the current client connection object: I'm
getting "Can't share GLOBS yet" error message. At the same time even when
the code works with "sleep 1", the threads don't seem to be able to close
the connection they inherited from the parent process. The code in "else"
block (not using threads) works just fine. I'm probably doing something
wrong with the threads. Does anyone know about any sample code I could look
at implementing the threads to handle the client connections?
Any help is greatly appreciated.
Thank you,
Maxim
package SoapDataDaemon;
# inherit this
use SOAP::Transport::HTTP;
@SoapDataDaemon::ISA = qw( SOAP::Transport::HTTP::Daemon );
# pragmas
use strict;
use warnings;
# multi-threaded version
use threads;
use threads::shared;
# version
our $VERSION = 1.000;
# Extension Modules
use Data::Dumper;
$Data::Dumper::Indent = 3;
use Log::Log4perl qw(:easy);
sub handle
{
my $self = shift;
my %args = @_;
# get the args
my $use_threads = $args{'use_threads'} || 0;
# get the logger
my $log = get_logger();
# which way are we going?
if ($use_threads) {
# run threads
if ($log->is_debug()) {
$log->debug("Using threads...");
}
# it's a copy of $self normally
my $daemon = $self->new();
# listening for connections
my $connection = 0;
while (my $conn = $daemon->accept) {
# increment the counter
$connection++;
if ($log->is_debug()) {
$log->debug("Main loop accepted connection $connection: ",
sub{Dumper($conn)});
}
# this will go in its own thread
my $thread = threads->create(\&process_request, $daemon, $conn);
$thread->detach();
if ($log->is_debug()) {
$log->debug("Main loop connection $connection after thtread:
", sub{Dumper($conn)});
}
#sleep 1;
} # while accept
} else {
if ($log->is_debug()) {
$log->debug("NOT Using threads...");
}
# it's a copy of $self normally
my $daemon = $self->new();
# listening for connections
while (my $conn = $daemon->accept) {
# get and process request
while (my $r = $conn->get_request) {
# handle request here
$daemon->request($r);
$daemon->SOAP::Transport::HTTP::Server::handle();
$conn->send_response($daemon->response);
} # while get_request
$conn->close();
undef $conn;
} # while accept
} # endif use_threads
} # handle
=head2 B<process_request()>
Process each request in its own thread
=cut
sub process_request
{
my $daemon = shift;
my $conn = shift;
my $log = get_logger();
if ($log->is_debug()) {
$log->debug("Thread: ", threads->tid(), " Conn: ",
sub{Dumper($conn)});
}
if ($log->is_debug()) {
$log->debug("Thread: ", threads->tid(), " Host: ",
$conn->peerhost(), " Port: ", $conn->peerport());
}
# get and process request
while (my $r = $conn->get_request) {
if ($log->is_debug()) {
$log->debug("Thread: ", threads->tid()," Processing request");
}
# handle request here
$daemon->request($r);
$daemon->SOAP::Transport::HTTP::Server::handle();
$conn->send_response($daemon->response);
} # while get_request
$conn->close();
undef $conn;
if ($log->is_debug()) {
$log->debug("Thread: ", threads->tid()," Connection closed.");
}
} # process_request