1/* 2 * Copyright (C) 2010 Apple Inc. All rights reserved. 3 * Portions Copyright (c) 2010 Motorola Mobility, Inc. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY MOTOROLA INC. AND ITS CONTRIBUTORS ``AS IS'' 15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 16 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MOTOROLA INC. OR ITS CONTRIBUTORS 18 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 22 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 24 * THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27#include "config.h" 28#include "ProcessLauncher.h" 29 30#include "Connection.h" 31#include "ProcessExecutablePath.h" 32#include <WebCore/AuthenticationChallenge.h> 33#include <WebCore/FileSystem.h> 34#include <WebCore/NetworkingContext.h> 35#include <WebCore/ResourceHandle.h> 36#include <errno.h> 37#include <fcntl.h> 38#include <glib.h> 39#include <locale.h> 40#include <wtf/RunLoop.h> 41#include <wtf/text/CString.h> 42#include <wtf/text/WTFString.h> 43#include <wtf/gobject/GUniquePtr.h> 44#include <wtf/gobject/GlibUtilities.h> 45 46using namespace WebCore; 47 48namespace WebKit { 49 50static void childSetupFunction(gpointer userData) 51{ 52 int socket = GPOINTER_TO_INT(userData); 53 close(socket); 54} 55 56void ProcessLauncher::launchProcess() 57{ 58 GPid pid = 0; 59 60 IPC::Connection::SocketPair socketPair = IPC::Connection::createPlatformConnection(IPC::Connection::ConnectionOptions::SetCloexecOnServer); 61 62 String executablePath, pluginPath; 63 CString realExecutablePath, realPluginPath; 64 switch (m_launchOptions.processType) { 65 case WebProcess: 66 executablePath = executablePathOfWebProcess(); 67 break; 68 case PluginProcess: 69 executablePath = executablePathOfPluginProcess(); 70 if (m_launchOptions.extraInitializationData.contains("requires-gtk2")) 71 executablePath.append('2'); 72 pluginPath = m_launchOptions.extraInitializationData.get("plugin-path"); 73 realPluginPath = fileSystemRepresentation(pluginPath); 74 break; 75#if ENABLE(NETWORK_PROCESS) 76 case NetworkProcess: 77 executablePath = executablePathOfNetworkProcess(); 78 break; 79#endif 80 default: 81 ASSERT_NOT_REACHED(); 82 return; 83 } 84 85 realExecutablePath = fileSystemRepresentation(executablePath); 86 GUniquePtr<gchar> socket(g_strdup_printf("%d", socketPair.client)); 87 88 unsigned nargs = 4; // size of the argv array for g_spawn_async() 89 90#ifndef NDEBUG 91 Vector<CString> prefixArgs; 92 if (!m_launchOptions.processCmdPrefix.isNull()) { 93 Vector<String> splitArgs; 94 m_launchOptions.processCmdPrefix.split(' ', splitArgs); 95 for (auto it = splitArgs.begin(); it != splitArgs.end(); it++) 96 prefixArgs.append(it->utf8()); 97 nargs += prefixArgs.size(); 98 } 99#endif 100 101 char** argv = g_newa(char*, nargs); 102 unsigned i = 0; 103#ifndef NDEBUG 104 // If there's a prefix command, put it before the rest of the args. 105 for (auto it = prefixArgs.begin(); it != prefixArgs.end(); it++) 106 argv[i++] = const_cast<char*>(it->data()); 107#endif 108 argv[i++] = const_cast<char*>(realExecutablePath.data()); 109 argv[i++] = socket.get(); 110 argv[i++] = const_cast<char*>(realPluginPath.data()); 111 argv[i++] = 0; 112 113 GUniqueOutPtr<GError> error; 114 if (!g_spawn_async(0, argv, 0, G_SPAWN_LEAVE_DESCRIPTORS_OPEN, childSetupFunction, GINT_TO_POINTER(socketPair.server), &pid, &error.outPtr())) { 115 g_printerr("Unable to fork a new WebProcess: %s.\n", error->message); 116 ASSERT_NOT_REACHED(); 117 } 118 119 // Don't expose the parent socket to potential future children. 120 while (fcntl(socketPair.client, F_SETFD, FD_CLOEXEC) == -1) 121 RELEASE_ASSERT(errno != EINTR); 122 123 close(socketPair.client); 124 m_processIdentifier = pid; 125 126 // We've finished launching the process, message back to the main run loop. 127 RunLoop::main().dispatch(bind(&ProcessLauncher::didFinishLaunchingProcess, this, m_processIdentifier, socketPair.server)); 128} 129 130void ProcessLauncher::terminateProcess() 131{ 132 if (m_isLaunching) { 133 invalidate(); 134 return; 135 } 136 137 if (!m_processIdentifier) 138 return; 139 140 kill(m_processIdentifier, SIGKILL); 141 m_processIdentifier = 0; 142} 143 144void ProcessLauncher::platformInvalidate() 145{ 146} 147 148} // namespace WebKit 149