Closed nelljerram closed 6 years ago
I guess it's this, from http://docs.python-requests.org/en/latest/user/advanced/#keep-alive:
Note that connections are only released back to the pool for reuse once all body data has been read; be sure to either set stream to False or read the content property of the Response object.
But since we don't tell the server that we're no longer interested in the watch, I'm not sure there's a correct definition of "once all body data has been read", and in practice accessing <watcher>._response.content
hangs for me.
I guess this is a known problem, and that this -
if six.PY2:
self._response.raw._fp.close()
is trying to work around it by reaching in and closing the socket by hand. But apparently it isn't working (with Python 2, which is what I'm using).
hey @neiljerram do you have time to throw a debugger at it? else i'll try to get to it next week
@dims Thanks for reading and commenting! I'm happy to try debugging if you can give me a bit more guidance on what to do or look for... at the moment I'm afraid I don't know what you have in mind.
@neiljerram oh, sorry. self._response.raw._fp.close()
stick the debugger on that line and step in to see if that actually closes the file pointer or it throws an exception somewhere and the file pointer is not closed.
Hi @dims, I work with Neil, I'm picking this up and trying to find a workaround. I believe that close()
is being called on the socket but it's still stuck open. I find that the code in the Python v3 branch of that function does seem to work for Python 2.7.12, the call to shutdown()
seems to do the trick.
I'm guessing you put the conditional there for a reason though?
From the python docs:
Note close() releases the resource associated with a connection but does not necessarily close the connection immediately. If you want to close the connection in a timely fashion, call shutdown() before close().
It doesn't seem like shutdown is new, looks like it's always been there.
@fasaxc if that works, then let's switch over to that. please make sure the unit tests work too. if i remember right, i had trouble with the unit tests too w/o that messy hack
I put up a PR; tox -e py27
passes for me locally. I noticed that the contributor guidelines say to follow the OpenStack process (via gerrit), is this an OpenStack project?
@fasaxc at some point i'll propose this to oslo. until then, this is my personal repo.
Run a local etcd server on port 2379, e.g. with
docker run --net=host quay.io/coreos/etcd
.Create an Etcd3Client and make an initial connection to the server:
Find out the PID of that python shell, and then in another window monitor its etcd connections with
You'll initially see that there is 1 connection:
Start and then cancel a watch:
The watch still shows just 1 connection.
However, now, for each further iteration of
we see 1 more ESTABLISHED connection. For example, after 8 more iterations, there are now 9 ESTABLISHED connections:
I believe this pattern continues without any bound, because in an overnight OpenStack churn test with networking-calico, the DHCP agent (which uses etcd3gw, and creates and cancels watches as above) was found to have more than 900 open connections to etcd.