IanB wrote:...If you have 2 apps chewing up ephemeral ports you could only have half that number available to you.
I was intending to allow getWizPnP to have a "ports in WAIT state" queue about 10% of the total available ephemeral ports.
IanB wrote:The KISS approach is to just just to spin on a socket in use error with a short sleep, say ~30ms, before the retry.
At the level of interface I'm using (LWP::Simple, and a bit of LWP::UserAgent), I don't directly get a "socket in use" error. I get a HTTP error (as
described earlier):
Code: Select all
500 Can't connect to w.z.y.z:49152 (connect: timeout).
on the expiration of the standard 180sec timeout (though I can control the length of this timeout). The timeout error comes pretty much straight from IO::Socket::INET->new(), so there appears to be a timeout on trying to allocate an ephemeral port, perhaps in connect(2). There seems little point in adding an extra delay here, because the 180sec timeout exceeds the 120sec WAIT state duration, and so by the time the timeout expires, all the ports previously in WAIT state that originated from getWizPnP should have completed their close. This points to a fairly ordinary implementation of waiting for the required resources to complete the connection.
So my current retry-based code is simply a retry loop with a 15sec internal timeout on the socket open, and a repeat count on that to bring it up to a total maximum wait of 180sec. No extra delays are necessary. Because the situation arises because getWizPnP is using up ephemeral ports faster than they can close down, it doesn't matter much that there could be up to 15sec of additional delay, because the program will quickly catch up and stall again.
The reason why I have moved away from this idea (though I may retain it as a "last stand" protection), is that it is triggered only when getWizPnP
has used up all the ephemeral ports, and is potentially interfering with other activities, as noted by Dennis (sub3r)
above.
IanB wrote:Burning 3976 ephemeral ports in 120 seconds is a fairly moderate rate of connects, ~31/sec.
The problem is caused by burning the 3976 ephemeral ports in
less than 120 sec. Dennis reports that the problem happens after about 85sec, for a port use rate of ~45/sec. The
reason that the ports are being burnt so fast is that --check, in contrast to any other getWizPnP functions, performs overwhelmingly HTTP HEAD requests, rather than GETs or POSTs. Probably part of the reason that it isn't even faster is the slowness of the Beyonwiz server, and the relative slowness of Perl over compiled code (even "compiled" versions of getWizPnP are interpreted, not compiled, even if they are in a .exe and superficially behave like compiled code).
IanB wrote:Perhaps bundling a .REG file to set a more reasonable limits would be a service to your users.
A couple of reasons for not doing this - it complicates the installation, and I don't have either the technical knowledge or the requisite software to create Windows setup.exe packages. I had a look at acquiring both, and was dismayed. The other is that I'm reluctant to make changes to central system parameters "behind the back" of users, even if the change is relatively innocuous, like increasing the size of the pool of ephemeral sockets. The other Registry changes that have been suggested I would simply not do in an installer, and probably not even recommend.
I appreciate the input from everyone (and most especially Dennis's efforts in tracking down the source of the problem), but I now want to implement and try my port wait queue idea to see to what extent it can be tuned to the execution environment of getWizPnP, and what effect it has on the speed of running getWizPnP. I don't think that the current behaviour of getWizPnP --check is fit for polite system society.