Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

Re: Strange blocking issue with HTTP::Daemon

by isync (Hermit)
on Aug 11, 2010 at 12:30 UTC ( [id://854344]=note: print w/replies, xml ) Need Help??


in reply to Strange blocking issue with HTTP::Daemon

Another post as I'd like to add a request for comments about what I've learned:

Result 1:
So HTTP::Daemon in essence behaves correctly, keeping connections alive on HTTP/1.1 requests, with the effect that this might block another client trying to connect.

This is a problem as long as HTTP::Daemon is single-threaded/non-forking, right? With a spawning HTTP::Daemon connection wrapper, although one connection might be doing keep-alive, there would be others idling waiting for connections, right?

Or do all the threads/forks still share a single socket, which is then blocked?

As said, I think I've seen this "blocking" behavior with forking Net::Server and assertively non-blocking AnyEvent::HTTPD based scripts - well, I think..
But forks sharing a single socket would explain this. But I again admit my limited understanding of socket workings.

Result 2:
Assuming that forks do not share a single (blocked) socket, a forking server might be able to serve keep-alive connections and closing ones side by side.
Adapting a ForkOnAccept concept from here, this is my result:
#!/usr/bin/perl use HTTP::Daemon; use Data::Dumper; my $d = HTTP::Daemon->new( LocalAddr => 'localhost', LocalPort => 4242, ReuseAddr => 1 ) || die; my $cnt; # response loop while (my $c = $d->accept) { my $pid = fork(); # We are going to close the new connection on one of two condition +s # 1. The fork failed ($pid is undefined) # 2. We are the parent ($pid != 0) if(!defined $pid || $pid == 0 ) { $c->close; print "Needs close: $pid\n"; next; } # From this point on, we are the child. # $c->close; # Close the listening socket (always done in childre +n) # Handle requests as they come in while (my $request = $c->get_request) { print "Request:\n".Dumper($request); my $response = HTTP::Response->new( 200, 'OK'); $response->header('Content-Type' => 'text/html'), $response->content("$cnt Working! (pid $pid)"); $cnt++; # print "Response:\n".Dumper($response); $c->send_response($response); } $c->close; undef($c); }
and guess what, it does work. (And on keep-alive connections the pid remains the same). Mh, although I get a lot of "Needs close: 0" messages from non-keep-alive clients. I think I need to think through fork()'ing again...

What's wrong/anything wrong with this design?

Replies are listed 'Best First'.
Re^2: Strange blocking issue with HTTP::Daemon
by Anonymous Monk on Aug 11, 2010 at 12:48 UTC
    What's wrong/anything wrong with this design?

    Nothing, its the standard way to do this sort of thing

      "Make it work, then make it fast!"

      Benchmark-wise this simple solution is slow due to the overhead of fork(). Now I see why people came up with schemes where a server forks on stock, so at any given time a ready-made fork is idling for a request. This forking-solution here gets creamed by the former/problematic non-forking one in ab...
        BTW: Can someone tell me why HTTP::Daemon, under stress-test, after a couple of hundred/thousand requests simply silently exits? With the client telling me "apr_socket_recv: Connection reset by peer (104)"?? (command ab -c 50 -n 5000 http://localhost:4242/ never reaches the 5000, always breaks at ~4800..)
        What can I use to debug exits which do not produce an error?

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://854344]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others meditating upon the Monastery: (7)
As of 2024-04-25 08:19 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found