square/okhttp — pull request #1178 by nfuller (2014-12-01 09:37:35+00:00)
Title: Fix for a socket leak in OkHttp on Android

When the preferred Android network changes from
cell -> wifi or wifi -> cell the HTTP connection
pool in use is abandoned to avoid reuse of
connections on the old network. This was added
in commit 8bced3e.

The design for the connection pool was such that
continuous use of the connection pool was required to
clean up idle / expired connections. If a connection
pool becomes idle (as when it is dereferenced on a
network change) it is possible for some connections
to remain in the pool indefinitely.

After the preferred network change, because the old
connection pool was no longer referenced the pool
would be garbage collected and Android's "Strict Mode"
would complain about sockets not being closed.

The only existing way to avoid this was to call
"evictAll()", which would have had issues when a
large number of connections were returned to the pool
after evictAll() was called. It also wouldn't work
for SPDY connections which are shared but not reference
counted, which makes knowing whether it is safe to
close them difficult. SPDY is not enabled on Android
by default and so that may have been safe to ignore.

This fix tries to keep the existing cleaning behavior
intact to avoid introducing new bugs or new thread
behavior that might impact battery life. It adds a
new mode to the pool for "draining", which handles
cleaning up any existing entries in the pool and any
added after the pool has been placed into draining
mode.

The drainModeRunnable introduced serves two purposes:

1) While scheduled / executing, it pins the connection
pool in memory to avoid it being garbage collected.
2) It continues to close connections (safely) until the
pool is empty.

If a connection is then added back to the pool the
drainModeRunnable is restarted.