1/* 2 Copyright (C) 2012 Samsung Electronics 3 Copyright (C) 2013 Nokia Corporation and/or its subsidiary(-ies). 4 5 This library is free software; you can redistribute it and/or 6 modify it under the terms of the GNU Library General Public 7 License as published by the Free Software Foundation; either 8 version 2 of the License, or (at your option) any later version. 9 10 This library is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 Library General Public License for more details. 14 15 You should have received a copy of the GNU Library General Public License 16 along with this library; see the file COPYING.LIB. If not, write to 17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 18 Boston, MA 02110-1301, USA. 19 */ 20 21#include "config.h" 22#include "ProcessLauncher.h" 23 24#include "Connection.h" 25#include "ProcessExecutablePath.h" 26#include <WebCore/AuthenticationChallenge.h> 27#include <WebCore/FileSystem.h> 28#include <WebCore/NetworkingContext.h> 29#include <WebCore/ResourceHandle.h> 30#include <sys/socket.h> 31#include <wtf/RunLoop.h> 32#include <wtf/StdLibExtras.h> 33#include <wtf/text/CString.h> 34#include <wtf/text/WTFString.h> 35 36using namespace WebCore; 37 38namespace WebKit { 39 40static Vector<std::unique_ptr<char[]>> createArgsArray(const String& prefix, const String& executablePath, const String& socket, const String& pluginPath) 41{ 42 ASSERT(!executablePath.isEmpty()); 43 ASSERT(!socket.isEmpty()); 44 45 Vector<String> splitArgs; 46 prefix.split(' ', splitArgs); 47 48 splitArgs.append(executablePath); 49 splitArgs.append(socket); 50 if (!pluginPath.isEmpty()) 51 splitArgs.append(pluginPath); 52 53 Vector<std::unique_ptr<char[]>> args; 54 args.resize(splitArgs.size() + 1); // Extra room for null. 55 56 size_t numArgs = splitArgs.size(); 57 for (size_t i = 0; i < numArgs; ++i) { 58 CString param = splitArgs[i].utf8(); 59 args[i] = std::make_unique<char[]>(param.length() + 1); // Room for the terminating null coming from the CString. 60 strncpy(args[i].get(), param.data(), param.length() + 1); // +1 here so that strncpy copies the ending null. 61 } 62 // execvp() needs the pointers' array to be null-terminated. 63 args[numArgs] = nullptr; 64 65 return args; 66} 67 68void ProcessLauncher::launchProcess() 69{ 70 int sockets[2]; 71 if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) < 0) { 72 ASSERT_NOT_REACHED(); 73 return; 74 } 75 76 String processCmdPrefix, executablePath, pluginPath; 77 switch (m_launchOptions.processType) { 78 case WebProcess: 79 executablePath = executablePathOfWebProcess(); 80 break; 81#if ENABLE(PLUGIN_PROCESS) 82 case PluginProcess: 83 executablePath = executablePathOfPluginProcess(); 84 pluginPath = m_launchOptions.extraInitializationData.get("plugin-path"); 85 break; 86#endif 87#if ENABLE(NETWORK_PROCESS) 88 case NetworkProcess: 89 executablePath = executablePathOfNetworkProcess(); 90 break; 91#endif 92 default: 93 ASSERT_NOT_REACHED(); 94 return; 95 } 96 97#ifndef NDEBUG 98 if (!m_launchOptions.processCmdPrefix.isEmpty()) 99 processCmdPrefix = m_launchOptions.processCmdPrefix; 100#endif 101 auto args = createArgsArray(processCmdPrefix, executablePath, String::number(sockets[0]), pluginPath); 102 103 // Do not perform memory allocation in the middle of the fork() 104 // exec() below. FastMalloc can potentially deadlock because 105 // the fork() doesn't inherit the running threads. 106 pid_t pid = fork(); 107 if (!pid) { // Child process. 108 close(sockets[1]); 109 execvp(args.data()[0].get(), reinterpret_cast<char* const*>(args.data())); 110 } else if (pid > 0) { // parent process; 111 close(sockets[0]); 112 m_processIdentifier = pid; 113 // We've finished launching the process, message back to the main run loop. 114 RunLoop::main().dispatch(bind(&ProcessLauncher::didFinishLaunchingProcess, this, pid, sockets[1])); 115 } else { 116 ASSERT_NOT_REACHED(); 117 return; 118 } 119} 120 121void ProcessLauncher::terminateProcess() 122{ 123 if (m_isLaunching) { 124 invalidate(); 125 return; 126 } 127 128 if (!m_processIdentifier) 129 return; 130 kill(m_processIdentifier, SIGKILL); 131 m_processIdentifier = 0; 132} 133 134void ProcessLauncher::platformInvalidate() 135{ 136} 137 138} // namespace WebKit 139