SPUG: Closing HTTP::Daemon port

Marc M. Adkins Marc.M.Adkins at Doorways.org
Wed Aug 13 01:23:41 CDT 2003


> First I'd like to say that this is a strange way to recycle a server. This
> is what I would call "in-band" control where the control is excerted over
> the same channel that the daemon normally operates through. Most programs
> will use an out-of-band control method either through signals or Unix
> sockets (e.g., postfix, named).

It was just simpler.  This is used on my home net, behind a firewall, so I
felt safe exposing the /quit URL.  That way I didn't have to complicate
things more than they already were.  If I had started on UNIX it might have
been different, but there are limitations on Windows and things that seem
simple on one side of the Great Divide are not so simple on the other.
Nevertheless, point taken, and in a production environment I would have felt
compelled to do as you say.

> Just a very brief skim over the code and playing, I came across this odd
> bit of code:
>
> while (my $page = get("http://localhost:$port/quit"))
>     {
>     logInfo("  Server Killed");
>     sleep 1;    # otherwise we occasionally try to start too fast
>     }
>
> The get() is being called by the second instance of the script which does
> indeed kill the first. But note that get() returns the requested document
> (which may be "true" or "false" depending on what was returned). get()
> returns undef in the event of a failure.

Y'know, it occurred to me after I logged off last night that maybe the loop
was trapping me.  But I just went and tested it.  I replaced the while with
an if and so it only gets hit once.  Same behavior.

[Moreover, I don't think that just now I was seeing the "Server Killed".
Which seems normal on the test server, as I'm returning an error condition.
On the real server it returns a good page and so it does in fact loop.]

As to why I used a while loop, it was something like killing a cockroach in
one's kitchen.  Hit it until it's dead and one more time for luck.  I was
just coding for the off chance that there were _two_ servers, one just wait
for the other to end, but of course with the delay in the system that can't
happen anyway.

In the full daemon there is actually code that reads the page that is
returned.  There is state that is thus preserved across instantiations.
This is another reason why the /quit works for me, it kills two cockroaches
with one shoe.  Using an out-of-band connection would have required a pipe
or socket to pass the state information, not just a system-wide semaphore or
whatever.

> On the network side of things, what I am seeing is a socket created by the
> second instance (by the get() call I presume) that hangs around for a
> minute in TIME_WAIT state. It's on the daemon's side of the connection
> (the first instance). So, I'm going to say that it is your daemon that's
> not cleaning up the socket after handling incoming requests. I can prove
> this by calling for arbitrary URIs on this port (repeatedly) and see
> half-dead sockets piling up on the daemons side. E.g., "wget
> http://localhost:9876/foobar". The TIME_WAIT sockets are not associated
> with any process. If I remembered more about the TIME_WAIT state, I'd know
> what this means. But I'm guessing that the daemon is releasing the socket
> before completely shutting it down after handling the request.

So...when I close the HTTP::Daemon object it isn't closing the listen port?
I haven't taken the time to crawl through that code yet...

mma




More information about the spug-list mailing list