Closed loucash closed 9 years ago
We could probably try to close the old socket with dlhttpc_sock:close(Sock, SSL)
or something in case it is indeed an error. If the connection was gone, it won't be a problem, though we'd risk making it even harder to detect.
Looking at it, it seems really freaking weird for the handler to set it to {active, once}
if we won't handle the messages or look for termination in handle_info
. I guess it's attempted more or less implicitly through trying to change the controlling process and reconnecting, but I can't remember why I wrote things that way initially. In any case, if it doesn't cause problems, that's fine.
In any case, good catch. Let's fail hard if it goes wrong. I'll merge this -- have you tried it on your own system or you're waiting for the merge for that?
:+1: for trying to close the old socket regardless
@ferd we'll be using our own fork for now, no rush here
@ferd Hey, I think console logs might not be really readable, let's go step by step:
send_request
and we get an error: {error, closed}
: https://github.com/ferd/dlhttpc/blob/master/src/dlhttpc_client.erl#L194 - we close old socket, create new onedispcount_watcher
receives: {'DOWN',_,process,_,normal}
dispcount_watcher
thinks someone lost its resource, runs dead
dead
creates new socketdispcount_watcher
as an owner, but reference is lostOld socket is closed, so there is no need to close it again. My fix is not to ignore new resource.
Yeah, I get that bit. I'm probably gonna be fine merging as is, but I wanted a bit of time figure out why I left things in {active,once}
. I guess it all hangs onto the fact it assumes the client did a good job of reading everything on the line, that the server didn't dump trailing content, and that the {active, once}
flag will let the worker detect if a connection has closed by polling, which makes sense, even I didn't exactly know it back then.
I'm also fine with not closing the socket as a preemptive measure. Let's crash systems that do not use the code properly and violently and see how that goes (that's what was happening right now!)
@ferd Hey. If you have an option
send_retry
set, then indlhttpc_client:send_request/1
(line 194) when we have an error{error, closed}
we retry, so we close current socket and we create new socket.Later we try to checkin this socket to dispcount handler, so first we change controlling process to the
dispcount_watcher
, and then... socket is not accepted (as it was new one). And that's a leak.I made a test in erlang shell. I mecked
dlhttpc_sock:send
to receive{error, closed}
when first time called. Then listed all ports before request and after request. After request there are 3 new ports, 1 responsible forinet_gethost 4
and 2 other linked todispcount_watcher
process - and there should be one.