From abd3142dcae02026689b939c363329b822b7cc0a Mon Sep 17 00:00:00 2001 From: Erik Kline Date: Fri, 15 May 2015 18:49:17 +0900 Subject: Close netlink socket when shutting down IpReachabilityMonitor This forces the NetlinkSocketObserver thread to exit quickly, rather than lingering until the next random netlink neighbor multicast message arrives. Additionally, add a small unittest to verify that multiple calls to NetlinkSocket#close() are safe. Change-Id: I101730fad7eee72f9c6e8a7e7bd10c634f2ceab4 --- core/java/android/net/IpReachabilityMonitor.java | 15 +++++++------- .../src/android/net/netlink/NetlinkSocketTest.java | 23 ++++++++++++++++++++++ 2 files changed, 31 insertions(+), 7 deletions(-) (limited to 'core') diff --git a/core/java/android/net/IpReachabilityMonitor.java b/core/java/android/net/IpReachabilityMonitor.java index add8774..cb8c866 100644 --- a/core/java/android/net/IpReachabilityMonitor.java +++ b/core/java/android/net/IpReachabilityMonitor.java @@ -73,7 +73,8 @@ public class IpReachabilityMonitor { private final Set mIpWatchList; private int mIpWatchListVersion; private boolean mRunning; - final private Thread mObserverThread; + private final NetlinkSocketObserver mNetlinkSocketObserver; + private final Thread mObserverThread; public IpReachabilityMonitor(String ifName, Callback callback) throws IllegalArgumentException { mInterfaceName = ifName; @@ -88,15 +89,15 @@ public class IpReachabilityMonitor { mIpWatchList = new HashSet(); mIpWatchListVersion = 0; mRunning = false; - mObserverThread = new Thread(new NetlinkSocketObserver()); + mNetlinkSocketObserver = new NetlinkSocketObserver(); + mObserverThread = new Thread(mNetlinkSocketObserver); mObserverThread.start(); } public void stop() { - synchronized (mLock) { - mRunning = false; - mIpWatchList.clear(); - } + synchronized (mLock) { mRunning = false; } + clearLinkProperties(); + mNetlinkSocketObserver.clearNetlinkSocket(); } // TODO: add a public dump() method that can be called during a bug report. @@ -251,6 +252,7 @@ public class IpReachabilityMonitor { } + // TODO: simply the number of objects by making this extend Thread. private final class NetlinkSocketObserver implements Runnable { private static final String TAG = "NetlinkSocketObserver"; private NetlinkSocket mSocket; @@ -292,7 +294,6 @@ public class IpReachabilityMonitor { if (mSocket != null) { mSocket.close(); } - mSocket = null; } // TODO: Refactor the main loop to recreate the socket upon recoverable errors. diff --git a/core/tests/coretests/src/android/net/netlink/NetlinkSocketTest.java b/core/tests/coretests/src/android/net/netlink/NetlinkSocketTest.java index b32de78..c599fe3 100644 --- a/core/tests/coretests/src/android/net/netlink/NetlinkSocketTest.java +++ b/core/tests/coretests/src/android/net/netlink/NetlinkSocketTest.java @@ -90,4 +90,27 @@ public class NetlinkSocketTest extends TestCase { s.close(); } + + public void testRepeatedCloseCallsAreQuiet() throws Exception { + // Create a working NetlinkSocket. + NetlinkSocket s = new NetlinkSocket(OsConstants.NETLINK_ROUTE); + assertNotNull(s); + s.connectToKernel(); + NetlinkSocketAddress localAddr = s.getLocalAddress(); + assertNotNull(localAddr); + assertEquals(0, localAddr.getGroupsMask()); + assertTrue(0 != localAddr.getPortId()); + // Close once. + s.close(); + // Test that it is closed. + boolean expectedErrorSeen = false; + try { + localAddr = s.getLocalAddress(); + } catch (ErrnoException e) { + expectedErrorSeen = true; + } + assertTrue(expectedErrorSeen); + // Close once more. + s.close(); + } } -- cgit v1.1