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(ListenerRequired=>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"; }