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 28b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeantimport java.io.IOException; 29b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeantimport java.io.FileDescriptor; 30b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeantimport java.util.ArrayList; 31b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant 32b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant/** 33b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant * Server socket class for zygote processes. 34b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant * 35b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant * Provides functions to wait for commands on a UNIX domain socket, and fork 36b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant * off child processes that inherit the initial state of the VM.% 37b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant * 38b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant * Please see {@link ZygoteConnection.Arguments} for documentation on the 39b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant * client protocol. 40b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant */ 41b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeantclass ZygoteServer { 42b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant public static final String TAG = "ZygoteServer"; 43b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant 44b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant private static final String ANDROID_SOCKET_PREFIX = "ANDROID_SOCKET_"; 45b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant 46b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant private LocalServerSocket mServerSocket; 47b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant 48b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant ZygoteServer() { 49b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant } 50b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant 51b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant /** 52b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant * Registers a server socket for zygote command connections 53b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant * 54b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant * @throws RuntimeException when open fails 55b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant */ 56b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant void registerServerSocket(String socketName) { 57b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant if (mServerSocket == null) { 58b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant int fileDesc; 59b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName; 60b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant try { 61b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant String env = System.getenv(fullSocketName); 62b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant fileDesc = Integer.parseInt(env); 63b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant } catch (RuntimeException ex) { 64b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant throw new RuntimeException(fullSocketName + " unset or invalid", ex); 65b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant } 66b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant 67b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant try { 68b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant FileDescriptor fd = new FileDescriptor(); 69b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant fd.setInt$(fileDesc); 70b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant mServerSocket = new LocalServerSocket(fd); 71b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant } catch (IOException ex) { 72b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant throw new RuntimeException( 73b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant "Error binding to local socket '" + fileDesc + "'", ex); 74b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant } 75b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant } 76b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant } 77b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant 78b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant /** 79b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant * Waits for and accepts a single command connection. Throws 80b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant * RuntimeException on failure. 81b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant */ 82b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant private ZygoteConnection acceptCommandPeer(String abiList) { 83b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant try { 84ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek return createNewConnection(mServerSocket.accept(), abiList); 85b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant } catch (IOException ex) { 86b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant throw new RuntimeException( 87b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant "IOException during accept()", ex); 88b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant } 89b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant } 90b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant 91ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek protected ZygoteConnection createNewConnection(LocalSocket socket, String abiList) 92ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek throws IOException { 93ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek return new ZygoteConnection(socket, abiList); 94ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek } 95ded209843616a98e6f97db0d1784f6d630cbd5e9Robert Sesek 96b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant /** 97b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant * Close and clean up zygote sockets. Called on shutdown and on the 98b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant * child's exit path. 99b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant */ 100b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant void closeServerSocket() { 101b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant try { 102b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant if (mServerSocket != null) { 103b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant FileDescriptor fd = mServerSocket.getFileDescriptor(); 104b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant mServerSocket.close(); 105b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant if (fd != null) { 106b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant Os.close(fd); 107b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant } 108b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant } 109b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant } catch (IOException ex) { 110b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant Log.e(TAG, "Zygote: error closing sockets", ex); 111b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant } catch (ErrnoException ex) { 112b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant Log.e(TAG, "Zygote: error closing descriptor", ex); 113b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant } 114b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant 115b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant mServerSocket = null; 116b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant } 117b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant 118b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant /** 119b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant * Return the server socket's underlying file descriptor, so that 120b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant * ZygoteConnection can pass it to the native code for proper 121b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant * closure after a child process is forked off. 122b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant */ 123b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant 124b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant FileDescriptor getServerSocketFileDescriptor() { 125b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant return mServerSocket.getFileDescriptor(); 126b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant } 127b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant 128b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant /** 129b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant * Runs the zygote process's select loop. Accepts new connections as 130b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant * they happen, and reads commands from connections one spawn-request's 131b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant * worth at a time. 132b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant * 133b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant * @throws Zygote.MethodAndArgsCaller in a child process when a main() 134b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant * should be executed. 135b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant */ 136b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant void runSelectLoop(String abiList) throws Zygote.MethodAndArgsCaller { 137b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>(); 138b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>(); 139b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant 140b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant fds.add(mServerSocket.getFileDescriptor()); 141b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant peers.add(null); 142b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant 143b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant while (true) { 144b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant StructPollfd[] pollFds = new StructPollfd[fds.size()]; 145b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant for (int i = 0; i < pollFds.length; ++i) { 146b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant pollFds[i] = new StructPollfd(); 147b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant pollFds[i].fd = fds.get(i); 148b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant pollFds[i].events = (short) POLLIN; 149b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant } 150b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant try { 151b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant Os.poll(pollFds, -1); 152b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant } catch (ErrnoException ex) { 153b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant throw new RuntimeException("poll failed", ex); 154b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant } 155b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant for (int i = pollFds.length - 1; i >= 0; --i) { 156b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant if ((pollFds[i].revents & POLLIN) == 0) { 157b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant continue; 158b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant } 159b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant if (i == 0) { 160b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant ZygoteConnection newPeer = acceptCommandPeer(abiList); 161b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant peers.add(newPeer); 162b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant fds.add(newPeer.getFileDesciptor()); 163b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant } else { 164b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant boolean done = peers.get(i).runOnce(this); 165b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant if (done) { 166b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant peers.remove(i); 167b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant fds.remove(i); 168b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant } 169b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant } 170b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant } 171b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant } 172b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant } 173b9679dc1fad508a001e30a941148e1bdc3fe953fTobias Sargeant} 174