1b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant/* 2b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant * Copyright (C) 2007 The Android Open Source Project 3b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant * 4b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant * Licensed under the Apache License, Version 2.0 (the "License"); 5b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant * you may not use this file except in compliance with the License. 6b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant * You may obtain a copy of the License at 7b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant * 8b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant * http://www.apache.org/licenses/LICENSE-2.0 9b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant * 10b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant * Unless required by applicable law or agreed to in writing, software 11b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant * distributed under the License is distributed on an "AS IS" BASIS, 12b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant * See the License for the specific language governing permissions and 14b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant * limitations under the License. 15b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant */ 16b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant 17b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeantpackage com.android.internal.os; 18b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant 19b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeantimport static android.system.OsConstants.POLLIN; 20b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant 21b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeantimport android.net.LocalServerSocket; 22ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesekimport android.net.LocalSocket; 23b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeantimport android.system.Os; 24b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeantimport android.system.ErrnoException; 25b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeantimport android.system.StructPollfd; 26b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeantimport android.util.Log; 27b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant 28ac0b4be198960ae56c3b484052bf3acccca59d22Narayan Kamathimport android.util.Slog; 29b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeantimport java.io.IOException; 30b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeantimport java.io.FileDescriptor; 31b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeantimport java.util.ArrayList; 32b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant 33b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant/** 34b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant * Server socket class for zygote processes. 35b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant * 36b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant * Provides functions to wait for commands on a UNIX domain socket, and fork 37b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant * off child processes that inherit the initial state of the VM.% 38b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant * 39b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant * Please see {@link ZygoteConnection.Arguments} for documentation on the 40b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant * client protocol. 41b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant */ 42b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeantclass ZygoteServer { 43b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant public static final String TAG = "ZygoteServer"; 44b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant 45b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant private static final String ANDROID_SOCKET_PREFIX = "ANDROID_SOCKET_"; 46b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant 47d0a190df8a04e10a6705148c02c5c4859ad75b70Robert Sesek /** 48d0a190df8a04e10a6705148c02c5c4859ad75b70Robert Sesek * Listening socket that accepts new server connections. 49d0a190df8a04e10a6705148c02c5c4859ad75b70Robert Sesek */ 50b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant private LocalServerSocket mServerSocket; 51b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant 52ac0b4be198960ae56c3b484052bf3acccca59d22Narayan Kamath /** 53d0a190df8a04e10a6705148c02c5c4859ad75b70Robert Sesek * Whether or not mServerSocket's underlying FD should be closed directly. 54d0a190df8a04e10a6705148c02c5c4859ad75b70Robert Sesek * If mServerSocket is created with an existing FD, closing the socket does 55d0a190df8a04e10a6705148c02c5c4859ad75b70Robert Sesek * not close the FD and it must be closed explicitly. If the socket is created 56d0a190df8a04e10a6705148c02c5c4859ad75b70Robert Sesek * with a name instead, then closing the socket will close the underlying FD 57d0a190df8a04e10a6705148c02c5c4859ad75b70Robert Sesek * and it should not be double-closed. 58d0a190df8a04e10a6705148c02c5c4859ad75b70Robert Sesek */ 59d0a190df8a04e10a6705148c02c5c4859ad75b70Robert Sesek private boolean mCloseSocketFd; 60d0a190df8a04e10a6705148c02c5c4859ad75b70Robert Sesek 61d0a190df8a04e10a6705148c02c5c4859ad75b70Robert Sesek /** 62ac0b4be198960ae56c3b484052bf3acccca59d22Narayan Kamath * Set by the child process, immediately after a call to {@code Zygote.forkAndSpecialize}. 63ac0b4be198960ae56c3b484052bf3acccca59d22Narayan Kamath */ 64ac0b4be198960ae56c3b484052bf3acccca59d22Narayan Kamath private boolean mIsForkChild; 65ac0b4be198960ae56c3b484052bf3acccca59d22Narayan Kamath 66b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant ZygoteServer() { 67b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant } 68b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant 69ac0b4be198960ae56c3b484052bf3acccca59d22Narayan Kamath void setForkChild() { 70ac0b4be198960ae56c3b484052bf3acccca59d22Narayan Kamath mIsForkChild = true; 71ac0b4be198960ae56c3b484052bf3acccca59d22Narayan Kamath } 72ac0b4be198960ae56c3b484052bf3acccca59d22Narayan Kamath 73b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant /** 74d0a190df8a04e10a6705148c02c5c4859ad75b70Robert Sesek * Registers a server socket for zygote command connections. This locates the server socket 75d0a190df8a04e10a6705148c02c5c4859ad75b70Robert Sesek * file descriptor through an ANDROID_SOCKET_ environment variable. 76b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant * 77b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant * @throws RuntimeException when open fails 78b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant */ 79d0a190df8a04e10a6705148c02c5c4859ad75b70Robert Sesek void registerServerSocketFromEnv(String socketName) { 80b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant if (mServerSocket == null) { 81b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant int fileDesc; 82b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName; 83b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant try { 84b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant String env = System.getenv(fullSocketName); 85b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant fileDesc = Integer.parseInt(env); 86b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant } catch (RuntimeException ex) { 87b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant throw new RuntimeException(fullSocketName + " unset or invalid", ex); 88b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant } 89b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant 90b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant try { 91b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant FileDescriptor fd = new FileDescriptor(); 92b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant fd.setInt$(fileDesc); 93b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant mServerSocket = new LocalServerSocket(fd); 94d0a190df8a04e10a6705148c02c5c4859ad75b70Robert Sesek mCloseSocketFd = true; 95b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant } catch (IOException ex) { 96b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant throw new RuntimeException( 97b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant "Error binding to local socket '" + fileDesc + "'", ex); 98b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant } 99b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant } 100b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant } 101b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant 102b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant /** 103d0a190df8a04e10a6705148c02c5c4859ad75b70Robert Sesek * Registers a server socket for zygote command connections. This opens the server socket 104d0a190df8a04e10a6705148c02c5c4859ad75b70Robert Sesek * at the specified name in the abstract socket namespace. 105d0a190df8a04e10a6705148c02c5c4859ad75b70Robert Sesek */ 106d0a190df8a04e10a6705148c02c5c4859ad75b70Robert Sesek void registerServerSocketAtAbstractName(String socketName) { 107d0a190df8a04e10a6705148c02c5c4859ad75b70Robert Sesek if (mServerSocket == null) { 108d0a190df8a04e10a6705148c02c5c4859ad75b70Robert Sesek try { 109d0a190df8a04e10a6705148c02c5c4859ad75b70Robert Sesek mServerSocket = new LocalServerSocket(socketName); 110d0a190df8a04e10a6705148c02c5c4859ad75b70Robert Sesek mCloseSocketFd = false; 111d0a190df8a04e10a6705148c02c5c4859ad75b70Robert Sesek } catch (IOException ex) { 112d0a190df8a04e10a6705148c02c5c4859ad75b70Robert Sesek throw new RuntimeException( 113d0a190df8a04e10a6705148c02c5c4859ad75b70Robert Sesek "Error binding to abstract socket '" + socketName + "'", ex); 114d0a190df8a04e10a6705148c02c5c4859ad75b70Robert Sesek } 115d0a190df8a04e10a6705148c02c5c4859ad75b70Robert Sesek } 116d0a190df8a04e10a6705148c02c5c4859ad75b70Robert Sesek } 117d0a190df8a04e10a6705148c02c5c4859ad75b70Robert Sesek 118d0a190df8a04e10a6705148c02c5c4859ad75b70Robert Sesek /** 119b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant * Waits for and accepts a single command connection. Throws 120b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant * RuntimeException on failure. 121b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant */ 122b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant private ZygoteConnection acceptCommandPeer(String abiList) { 123b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant try { 124ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek return createNewConnection(mServerSocket.accept(), abiList); 125b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant } catch (IOException ex) { 126b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant throw new RuntimeException( 127b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant "IOException during accept()", ex); 128b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant } 129b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant } 130b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant 131ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek protected ZygoteConnection createNewConnection(LocalSocket socket, String abiList) 132ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek throws IOException { 133ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek return new ZygoteConnection(socket, abiList); 134ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek } 135ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek 136b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant /** 137b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant * Close and clean up zygote sockets. Called on shutdown and on the 138b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant * child's exit path. 139b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant */ 140b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant void closeServerSocket() { 141b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant try { 142b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant if (mServerSocket != null) { 143b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant FileDescriptor fd = mServerSocket.getFileDescriptor(); 144b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant mServerSocket.close(); 145d0a190df8a04e10a6705148c02c5c4859ad75b70Robert Sesek if (fd != null && mCloseSocketFd) { 146b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant Os.close(fd); 147b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant } 148b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant } 149b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant } catch (IOException ex) { 150b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant Log.e(TAG, "Zygote: error closing sockets", ex); 151b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant } catch (ErrnoException ex) { 152b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant Log.e(TAG, "Zygote: error closing descriptor", ex); 153b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant } 154b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant 155b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant mServerSocket = null; 156b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant } 157b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant 158b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant /** 159b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant * Return the server socket's underlying file descriptor, so that 160b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant * ZygoteConnection can pass it to the native code for proper 161b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant * closure after a child process is forked off. 162b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant */ 163b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant 164b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant FileDescriptor getServerSocketFileDescriptor() { 165b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant return mServerSocket.getFileDescriptor(); 166b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant } 167b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant 168b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant /** 169b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant * Runs the zygote process's select loop. Accepts new connections as 170b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant * they happen, and reads commands from connections one spawn-request's 171b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant * worth at a time. 172b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant */ 173ac0b4be198960ae56c3b484052bf3acccca59d22Narayan Kamath Runnable runSelectLoop(String abiList) { 174b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>(); 175b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>(); 176b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant 177b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant fds.add(mServerSocket.getFileDescriptor()); 178b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant peers.add(null); 179b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant 180b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant while (true) { 181b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant StructPollfd[] pollFds = new StructPollfd[fds.size()]; 182b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant for (int i = 0; i < pollFds.length; ++i) { 183b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant pollFds[i] = new StructPollfd(); 184b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant pollFds[i].fd = fds.get(i); 185b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant pollFds[i].events = (short) POLLIN; 186b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant } 187b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant try { 188b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant Os.poll(pollFds, -1); 189b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant } catch (ErrnoException ex) { 190b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant throw new RuntimeException("poll failed", ex); 191b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant } 192b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant for (int i = pollFds.length - 1; i >= 0; --i) { 193b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant if ((pollFds[i].revents & POLLIN) == 0) { 194b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant continue; 195b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant } 196ac0b4be198960ae56c3b484052bf3acccca59d22Narayan Kamath 197b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant if (i == 0) { 198b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant ZygoteConnection newPeer = acceptCommandPeer(abiList); 199b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant peers.add(newPeer); 200b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant fds.add(newPeer.getFileDesciptor()); 201b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant } else { 202ac0b4be198960ae56c3b484052bf3acccca59d22Narayan Kamath try { 203ac0b4be198960ae56c3b484052bf3acccca59d22Narayan Kamath ZygoteConnection connection = peers.get(i); 204ac0b4be198960ae56c3b484052bf3acccca59d22Narayan Kamath final Runnable command = connection.processOneCommand(this); 205ac0b4be198960ae56c3b484052bf3acccca59d22Narayan Kamath 206ac0b4be198960ae56c3b484052bf3acccca59d22Narayan Kamath if (mIsForkChild) { 207ac0b4be198960ae56c3b484052bf3acccca59d22Narayan Kamath // We're in the child. We should always have a command to run at this 208ac0b4be198960ae56c3b484052bf3acccca59d22Narayan Kamath // stage if processOneCommand hasn't called "exec". 209ac0b4be198960ae56c3b484052bf3acccca59d22Narayan Kamath if (command == null) { 210ac0b4be198960ae56c3b484052bf3acccca59d22Narayan Kamath throw new IllegalStateException("command == null"); 211ac0b4be198960ae56c3b484052bf3acccca59d22Narayan Kamath } 212ac0b4be198960ae56c3b484052bf3acccca59d22Narayan Kamath 213ac0b4be198960ae56c3b484052bf3acccca59d22Narayan Kamath return command; 214ac0b4be198960ae56c3b484052bf3acccca59d22Narayan Kamath } else { 215ac0b4be198960ae56c3b484052bf3acccca59d22Narayan Kamath // We're in the server - we should never have any commands to run. 216ac0b4be198960ae56c3b484052bf3acccca59d22Narayan Kamath if (command != null) { 217ac0b4be198960ae56c3b484052bf3acccca59d22Narayan Kamath throw new IllegalStateException("command != null"); 218ac0b4be198960ae56c3b484052bf3acccca59d22Narayan Kamath } 219ac0b4be198960ae56c3b484052bf3acccca59d22Narayan Kamath 220ac0b4be198960ae56c3b484052bf3acccca59d22Narayan Kamath // We don't know whether the remote side of the socket was closed or 221ac0b4be198960ae56c3b484052bf3acccca59d22Narayan Kamath // not until we attempt to read from it from processOneCommand. This shows up as 222ac0b4be198960ae56c3b484052bf3acccca59d22Narayan Kamath // a regular POLLIN event in our regular processing loop. 223ac0b4be198960ae56c3b484052bf3acccca59d22Narayan Kamath if (connection.isClosedByPeer()) { 224ac0b4be198960ae56c3b484052bf3acccca59d22Narayan Kamath connection.closeSocket(); 225ac0b4be198960ae56c3b484052bf3acccca59d22Narayan Kamath peers.remove(i); 226ac0b4be198960ae56c3b484052bf3acccca59d22Narayan Kamath fds.remove(i); 227ac0b4be198960ae56c3b484052bf3acccca59d22Narayan Kamath } 228ac0b4be198960ae56c3b484052bf3acccca59d22Narayan Kamath } 229ac0b4be198960ae56c3b484052bf3acccca59d22Narayan Kamath } catch (Exception e) { 230ac0b4be198960ae56c3b484052bf3acccca59d22Narayan Kamath if (!mIsForkChild) { 231ac0b4be198960ae56c3b484052bf3acccca59d22Narayan Kamath // We're in the server so any exception here is one that has taken place 232ac0b4be198960ae56c3b484052bf3acccca59d22Narayan Kamath // pre-fork while processing commands or reading / writing from the 233ac0b4be198960ae56c3b484052bf3acccca59d22Narayan Kamath // control socket. Make a loud noise about any such exceptions so that 234ac0b4be198960ae56c3b484052bf3acccca59d22Narayan Kamath // we know exactly what failed and why. 235ac0b4be198960ae56c3b484052bf3acccca59d22Narayan Kamath 236ac0b4be198960ae56c3b484052bf3acccca59d22Narayan Kamath Slog.e(TAG, "Exception executing zygote command: ", e); 237ac0b4be198960ae56c3b484052bf3acccca59d22Narayan Kamath 238ac0b4be198960ae56c3b484052bf3acccca59d22Narayan Kamath // Make sure the socket is closed so that the other end knows immediately 239ac0b4be198960ae56c3b484052bf3acccca59d22Narayan Kamath // that something has gone wrong and doesn't time out waiting for a 240ac0b4be198960ae56c3b484052bf3acccca59d22Narayan Kamath // response. 241ac0b4be198960ae56c3b484052bf3acccca59d22Narayan Kamath ZygoteConnection conn = peers.remove(i); 242ac0b4be198960ae56c3b484052bf3acccca59d22Narayan Kamath conn.closeSocket(); 243ac0b4be198960ae56c3b484052bf3acccca59d22Narayan Kamath 244ac0b4be198960ae56c3b484052bf3acccca59d22Narayan Kamath fds.remove(i); 245ac0b4be198960ae56c3b484052bf3acccca59d22Narayan Kamath } else { 246ac0b4be198960ae56c3b484052bf3acccca59d22Narayan Kamath // We're in the child so any exception caught here has happened post 247ac0b4be198960ae56c3b484052bf3acccca59d22Narayan Kamath // fork and before we execute ActivityThread.main (or any other main() 248ac0b4be198960ae56c3b484052bf3acccca59d22Narayan Kamath // method). Log the details of the exception and bring down the process. 249ac0b4be198960ae56c3b484052bf3acccca59d22Narayan Kamath Log.e(TAG, "Caught post-fork exception in child process.", e); 250ac0b4be198960ae56c3b484052bf3acccca59d22Narayan Kamath throw e; 251ac0b4be198960ae56c3b484052bf3acccca59d22Narayan Kamath } 252d0a190df8a04e10a6705148c02c5c4859ad75b70Robert Sesek } finally { 253d0a190df8a04e10a6705148c02c5c4859ad75b70Robert Sesek // Reset the child flag, in the event that the child process is a child- 254d0a190df8a04e10a6705148c02c5c4859ad75b70Robert Sesek // zygote. The flag will not be consulted this loop pass after the Runnable 255d0a190df8a04e10a6705148c02c5c4859ad75b70Robert Sesek // is returned. 256d0a190df8a04e10a6705148c02c5c4859ad75b70Robert Sesek mIsForkChild = false; 257b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant } 258b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant } 259b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant } 260b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant } 261b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant } 262b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant} 263