diff options
author | Chia-chi Yeh <chiachi@android.com> | 2011-08-22 13:09:49 -0700 |
---|---|---|
committer | Chia-chi Yeh <chiachi@android.com> | 2011-08-22 13:09:49 -0700 |
commit | 5317f034bacaab19af3181da8e9752cbb5b09a08 (patch) | |
tree | cc498387446d2ee763f887f874584d968f2c6738 /services/java/com/android/server/connectivity/Vpn.java | |
parent | 583b163feb9266d3b2080810a30ac68c7bd4760e (diff) | |
download | frameworks_base-5317f034bacaab19af3181da8e9752cbb5b09a08.zip frameworks_base-5317f034bacaab19af3181da8e9752cbb5b09a08.tar.gz frameworks_base-5317f034bacaab19af3181da8e9752cbb5b09a08.tar.bz2 |
VPN: stop daemons by closing the control sockets.
As init now uses SIGKILL to stop daemons, performing graceful shutdown
becomes impossible. Here we implement our own solution by asking daemons
to monitor the control socket and terminate when it is closed.
Change-Id: I07a28807173a81b7f95e70f4193e974317acf88a
Diffstat (limited to 'services/java/com/android/server/connectivity/Vpn.java')
-rw-r--r-- | services/java/com/android/server/connectivity/Vpn.java | 42 |
1 files changed, 25 insertions, 17 deletions
diff --git a/services/java/com/android/server/connectivity/Vpn.java b/services/java/com/android/server/connectivity/Vpn.java index 6b65e07..55e0678 100644 --- a/services/java/com/android/server/connectivity/Vpn.java +++ b/services/java/com/android/server/connectivity/Vpn.java @@ -388,6 +388,7 @@ public class Vpn extends INetworkManagementEventObserver.Stub { private final VpnConfig mConfig; private final String[] mDaemons; private final String[][] mArguments; + private final LocalSocket[] mSockets; private final String mOuterInterface; private final LegacyVpnInfo mInfo; @@ -398,6 +399,7 @@ public class Vpn extends INetworkManagementEventObserver.Stub { mConfig = config; mDaemons = new String[] {"racoon", "mtpd"}; mArguments = new String[][] {racoon, mtpd}; + mSockets = new LocalSocket[mDaemons.length]; mInfo = new LegacyVpnInfo(); // This is the interface which VPN is running on. @@ -416,10 +418,14 @@ public class Vpn extends INetworkManagementEventObserver.Stub { } public void exit() { - // We assume that everything is reset after the daemons die. + // We assume that everything is reset after stopping the daemons. interrupt(); - for (String daemon : mDaemons) { - SystemProperties.set("ctl.stop", daemon); + for (LocalSocket socket : mSockets) { + try { + socket.close(); + } catch (Exception e) { + // ignore + } } } @@ -462,15 +468,10 @@ public class Vpn extends INetworkManagementEventObserver.Stub { checkpoint(false); mInfo.state = LegacyVpnInfo.STATE_INITIALIZING; - // First stop the daemons. - for (String daemon : mDaemons) { - SystemProperties.set("ctl.stop", daemon); - } - // Wait for the daemons to stop. for (String daemon : mDaemons) { String key = "init.svc." + daemon; - while (!"stopped".equals(SystemProperties.get(key))) { + while (!"stopped".equals(SystemProperties.get(key, "stopped"))) { checkpoint(true); } } @@ -511,27 +512,27 @@ public class Vpn extends INetworkManagementEventObserver.Stub { } // Create the control socket. - LocalSocket socket = new LocalSocket(); + mSockets[i] = new LocalSocket(); LocalSocketAddress address = new LocalSocketAddress( daemon, LocalSocketAddress.Namespace.RESERVED); // Wait for the socket to connect. while (true) { try { - socket.connect(address); + mSockets[i].connect(address); break; } catch (Exception e) { // ignore } checkpoint(true); } - socket.setSoTimeout(500); + mSockets[i].setSoTimeout(500); // Send over the arguments. - OutputStream out = socket.getOutputStream(); + OutputStream out = mSockets[i].getOutputStream(); for (String argument : arguments) { byte[] bytes = argument.getBytes(Charsets.UTF_8); - if (bytes.length > 0xFFFF) { + if (bytes.length >= 0xFFFF) { throw new IllegalArgumentException("Argument is too large"); } out.write(bytes.length >> 8); @@ -539,11 +540,12 @@ public class Vpn extends INetworkManagementEventObserver.Stub { out.write(bytes); checkpoint(false); } + out.write(0xFF); + out.write(0xFF); out.flush(); - socket.shutdownOutput(); // Wait for End-of-File. - InputStream in = socket.getInputStream(); + InputStream in = mSockets[i].getInputStream(); while (true) { try { if (in.read() == -1) { @@ -554,7 +556,6 @@ public class Vpn extends INetworkManagementEventObserver.Stub { } checkpoint(true); } - socket.close(); } // Wait for the daemons to create the new state. @@ -631,6 +632,13 @@ public class Vpn extends INetworkManagementEventObserver.Stub { Log.i(TAG, "Aborting", e); exit(); } finally { + // Kill the daemons if they fail to stop. + if (mInfo.state == LegacyVpnInfo.STATE_INITIALIZING) { + for (String daemon : mDaemons) { + SystemProperties.set("ctl.stop", daemon); + } + } + // Do not leave an unstable state. if (mInfo.state == LegacyVpnInfo.STATE_INITIALIZING || mInfo.state == LegacyVpnInfo.STATE_CONNECTING) { |