For Programmers: Free Programming Magazines  


Home > Archive > ithreads > June 2007 > Threads mess with simple HTTP daemon









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author Threads mess with simple HTTP daemon
Arno Velds

2007-06-14, 8:18 am

I've been working on a simple http server that keeps a pool of threads
around that do multiple crops on an image.

It's a very simple blocking webserver that handles 1 request per
connection. It uses a Thread::Queue::Multiplex (TQM) to assign the
request to the corresponding image cropping thread using the
enqueue_and_wait function. The image threads use the dequeue_until
function to limit their lifetime.

After a connection is made and the url is parsed it first checks with
the TQM for a listener with that image id. If it doesn't exist it will
immediately detach a new thread for that image and sleep for a couple
of seconds. The image thread registers as a listener with the TQM and
serves a tiny jpg image as a response to the TQM.

This works perfectly fine except that the request following the thread
starting request from the same client is never answered. Subsequent
requests as well as requests from other clients are handled without
any problems. The strange thing is that the browser will wait until
the image thread finishes and then re-requests the image. If you
tunnel the request through an apache proxy (as I intend to do) it
raises an error. So it seems somehow this thread starting messes with
the (HTTP, TCP/IP?) connection.

I've looked a little bit at the network traffic using wireshark and
did notice that the first request never exchanges a FIN, ACK with the
server. But that stuff is way over my head :-)

I cleaned up my program a bit and pasted it below. It now just tosses
around text strings, but it still shows the same behavior on my
computer (i386 Ubunbtu feisty, perl 5.8.8). It starts a local server
on port 8080 and handles urls in the form of http://localhost/<number>/<number>
.. You can start the program, do a request from your browser and wait
for the answer, then press the reload button. The browser will wait
until the image thread times out (40 seconds), then re-request.

Do you think this is a bug? Should I report this somewhere?

BTW, I worked around this problem by creating a thread starting thread
that listens to another queue so no more threads are started from
within the connection loop. This works fine, but it is a bit of a
hack!

Regards, Arno


Example program:

#!/usr/bin/perl

use strict;
use warnings;

use threads;
use Thread::Queue::Multiplex;

use HTTP::Daemon;
use HTTP::Response;
use HTTP::Status;


$|=1;

my $requestqueue_store = new
Thread::Queue::Multiplex(ListenerRequire
d=>0);

my $d = HTTP::Daemon->new(Listen=>10,LocalPort=>8080, ReuseAddr=>1) ||
die;
print "Please contact me at: <URL:", $d->url, ">\n";
while (my $c = $d->accept) {
print "connection!\n";
while(my $r = $c->get_request) {
$c->force_last_request;
if ($r->method eq 'GET' and $r->url->path =~ m/\/(\d+)\/(\d+)\/
{0,1}$/) {
my $hybid = $1;
my $featureid = $2;
print "W-hybid = $hybid, featureid = $featureid\n";

#do we hava a running thread for this hyb?
my @subids = $requestqueue_store->get_subscribers();

if((grep {$_ == $hybid} @subids) == 0) {
#spawn new thread
print "W- Creating new image thread...";
threads->create("image_thread", $hybid)->detach;
sleep 2;
}

#queue request and wait for response
my $img_resp = $requestqueue_store->enqueue_and_wait($hybid,
$featureid);
my $img = $img_resp->{$hybid}->[0];

my $resp = new HTTP::Response(200);
$resp->content($img);
$resp->header('content_type'=>'text/html',
data_lenght=>length($img));
print "W-Sending data\n";

$c->send_response($resp);
}
else {
$c->send_error(RC_FORBIDDEN)
}
}
print "W- Closing connection\n";
$c->close();

}

sub image_thread {
my $hybid = shift;
$requestqueue_store->subscribe($hybid);

my $tid = threads->self->tid;

print "I-($tid) Testthread for $hybid...";

print "I-($tid) is Waiting\n";
while(my $msg = $requestqueue_store->dequeue_until(40)) {
if(not defined $msg) {
print "I-($tid) inactive for 40\n";
last;
}
my $id = $msg->[0];
my $featureid = $msg->[1];
print "I-($tid)-Got request for $featureid, msgid=$id\n";

my $response = "You requested $featureid, and I ($hybid) served!\n";

#queue the response
$requestqueue_store->respond($id, $response);
my $response = "Answer sent";
}
print "I-($tid) Exiting thread\n";
print "I-($tid) cleaned up modules, deregister listener\n";
$requestqueue_store->unsubscribe();
print "I-($tid) all done...exiting\n";
}

Princces

2007-06-14, 3:20 pm

Halle Berry and Jennifer Aniston Hot Lesbian Girls And Their Games!
http://www.freedutchmovies.com/Play...hp?clip=1673286

Shania Twain and Hilary Duff At Pillow War Game!
http://www.freedutchmovies.com/Play...g?watch=1673286

Jessica Simpson and Jennifer Aniston Crazy On High Heels!
http://www.freedutchmovies.com/a?vid=1673286

Jennifer Aniston and Jennifer Aniston Using Massage Machine!
http://www.freedutchmovies.com/WatchTube?q=1673286

Mariah Carey and Pamela Anderson Go Lesbian!
http://www.freedutchmovies.com/WatchTube?vid=1673286
Jerry D. Hedden

2007-06-14, 7:19 pm

On Arno Velds wrote:
> This works perfectly fine except that the request following the thread
> starting request from the same client is never answered.


If you remove the line:
$c->force_last_request;
then it works as advertised.
Arno Velds

2007-06-15, 8:19 am

On 14 jun, 20:41, jdhed...@cpan.org (Jerry D. Hedden) wrote:
> On Arno Velds wrote:
>
> If you remove the line:
> $c->force_last_request;
> then it works as advertised.


Thanks for thinking along. You are correct, but this has some
divantages. Standard firefox keepalive time is 300 seconds. So
unless you use a threaded webserver implementation this will block all
other incoming requests. I obviously tried this, but performance is
lower than allowing only one request per connection.

As I mentioned in my somewhat lengthy post I have already worked
around the problem by not starting new threads from the connection
loop. All I would like to know is that if I want to be a HTTP/1.0
server and only serve 1 request per connection why isn't the second
request from the same client answered even though they can be 20
seconds apart and separated by a $c->close on the server side. Please
bear in mind that the second request is not being discarded by the $c-
>force_last_request; because at that time it hasn't even been sent!


Maybe you can try my example and see for yourself.

Cheers,
Arno (The Netherlands)






Jerry D. Hedden

2007-06-15, 7:25 pm

Arno Velds wrote:
> As I mentioned in my somewhat lengthy post I have already worked
> around the problem by not starting new threads from the connection
> All I would like to know is that if I want to be a HTTP/1.0
> server and only serve 1 request per connection why isn't the second
> request from the same client answered even though they can be 20
> seconds apart and separated by a $c->close on the server side.


If you want to be HTTP/1.0, then you need to tell the browser that.
You do this by setting:
$HTTP::Daemon::PROTO = "HTTP/1.0";
This is then sent with the response so that the browser knows you're
not going to service another request on this socket.
Arno Velds

2007-06-15, 7:25 pm

On 15 jun, 15:10, jdhed...@cpan.org (Jerry D. Hedden) wrote:
> Arno Velds wrote:
>
> If you want to be HTTP/1.0, then you need to tell the browser that.
> You do this by setting:
> $HTTP::Daemon::PROTO = "HTTP/1.0";
> This is then sent with the response so that the browser knows you're
> not going to service another request on this socket.


Check....Now I feel silly....

Still, I don't even remotely understand why the exiting of the image
thread has any relation with the browser timeout on this weird form of
HTTP/1.0 - HTTP/1.1 miscommunication. Oh well...

Thanks!

Jerry D. Hedden

2007-06-15, 7:25 pm

Arno Velds wrote:
> Still, I don't even remotely understand why the exiting of the image
> thread has any relation with the browser timeout on this weird form of
> HTTP/1.0 - HTTP/1.1 miscommunication.


It's because the thread still has the socket open. If you pass the
socket to the thread:
threads->create("image_thread", $hybid, $c)->detach;

And then close it in the thread:
sub image_thread {
my $hybid = shift;
my $socket = shift;
$socket->close();
...

You don't get that problem.
Skiller

2007-06-23, 4:29 am

Hilary Swank Spreading Juicy Pussy Outdoor!

http://www.WatchingTheTube.com/watch?vid=1673286



video download sexy funny funny video wii funny more naruto very video animal funny video zoo sex funny cartoon video
http://635-funny-video.info/clip-fr...line-video.html http://635-funny-video.info/but-fun...ideo-weird.html http://635-funny-video.info/funny-music-video-clip.html http://635-funny-video.info/funny-clean-video-clip.html http://635-funny-video.info/XXXXing...shit-video.html
Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com