Subject: | all file descriptors are eventually leaked if the files to be 'auto-refreshed' never change |
The inserted .js that the AutoRefresh middleware inserts into the
webpage opens a new connection to the server every 1500ms, and
Plack::Middleware::AutoRefresh keeps this tcp session open (on the
server side) until there is a change of files in the watched directory.
So you leak an fd every 1500ms. If no files change before you run out
of TCP connection file descriptors, then Plack::Server::AnyEvent wedges
in a tight (CPU-intensive) run-loop because accept() fails to block when
it cant allocate any new file-descriptors.
#----------------------------------------
# Steps to recreate:
#----------------------------------------
#save this file:
#------------- app.psgi -----------------
#!/usr/bin/perl
use Plack::Builder;
builder {
enable 'Plack::Middleware::AutoRefresh';
sub {
[
200,
[ 'content-type' => 'text/html' ],
[ '<html><head></head><body>hello world</body></html>' ]
]
}
};
#----------------------------------------
MacOS 10.6 prompt> ls
app.psgi
MacOS 10.6 prompt> plackup -s Plack::Server::AnyEvent
Accepting requests at http://0.0.0.0:5000/
127.0.0.1 - - [30/Mar/2010 11:05:53] "GET / HTTP/1.1" 200 3164 "-"
"Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; en-US; rv:1.9.2)
Gecko/20100115 Firefox/3.6"
#---------------------------------------
# load localhost:5000 in your browser (I used firefox 3.6)
#---------------------------------------
# Watch the output of lsof and see another fd leaked each 1500ms in
(CLOSE_WAIT) state:
#---------------------------------------
MacOS 10.6 prompt> lsof | grep perl
# ...
localhost:commplex-main->localhost:55086 (CLOSE_WAIT)
perl5.10. 59853 ashleydev 16u IPv4 0x1b2702d4 0t0 TCP
localhost:commplex-main->localhost:55089 (CLOSE_WAIT)
perl5.10. 59853 ashleydev 17u IPv4 0x1af4ba8c 0t0 TCP
localhost:commplex-main->localhost:55092 (CLOSE_WAIT)
perl5.10. 59853 ashleydev 18u IPv4 0x19605abc 0t0 TCP
localhost:commplex-main->localhost:55097 (CLOSE_WAIT)
perl5.10. 59853 ashleydev 19u IPv4 0x1661f274 0t0 TCP
localhost:commplex-main->localhost:55102 (CLOSE_WAIT)
perl5.10. 59853 ashleydev 20u IPv4 0x19609274 0t0 TCP
localhost:commplex-main->localhost:55105 (CLOSE_WAIT)
perl5.10. 59853 ashleydev 21u IPv4 0x1960ea8c 0t0 TCP
localhost:commplex-main->localhost:55109 (CLOSE_WAIT)
perl5.10. 59853 ashlyedev 22u IPv4 0x19612b4c 0t0 TCP
localhost:commplex-main->localhost:55112 (CLOSE_WAIT)
perl5.10. 59853 ashleydev 23u IPv4 0x09f5cabc 0t0 TCP
localhost:commplex-main->localhost:55115 (CLOSE_WAIT)
#---------------------------------------
# if you `touch app.psgi` you will see all of those `CLOSE_WAIT` tcp
connections go away. However if you let it sit there for a day, then
when all the file descriptors are used up, the plackup server will
wedge, not accept'ing anymore connections and will run up the CPU in a
tight select() loop.
# solution: I hesitate to provide one since I'm not so well acquainted
with the code yet, but I'd assume there's a way have it work without the
inserted .js open a new tcp connection and keep it open when there are
no changes on the web-server to push.