Changeset 204414 in webkit
- Timestamp:
- Aug 12, 2016, 11:50:02 AM (9 years ago)
- Location:
- trunk/Source/WebKit2
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebKit2/ChangeLog
r204401 r204414 1 2016-08-12 Anders Carlsson <andersca@apple.com> 2 3 message loading never finishes in Mail 4 https://bugs.webkit.org/show_bug.cgi?id=160806 5 rdar://problem/27624095 6 7 Reviewed by Dan Bernstein. 8 9 Add more checks for when a process goes away before we've established a proper connection to it. 10 11 * Platform/IPC/mac/ConnectionMac.mm: 12 (IPC::Connection::receiveSourceEventHandler): 13 Handle the MACH_NOTIFY_NO_SENDERS and MACH_NOTIFY_SEND_ONCE messages here. Also, once we receive a send 14 right from the other side, stop listening for the MACH_NOTIFY_NO_SENDERS notification. 15 16 * UIProcess/ChildProcessProxy.cpp: 17 (WebKit::ChildProcessProxy::didFinishLaunching): 18 Null check the connection identifier. 19 20 * UIProcess/Launcher/ProcessLauncher.cpp: 21 (WebKit::ProcessLauncher::ProcessLauncher): 22 (WebKit::processLauncherWorkQueue): Deleted. 23 Get rid of the process launcher queue - we're not doing any blocking work here. 24 25 * UIProcess/Launcher/ProcessLauncher.h: 26 Add a weak factory. 27 28 * UIProcess/Launcher/mac/ProcessLauncherMac.mm: 29 (WebKit::systemDirectoryPath): 30 Move this before launchProcess(). 31 32 (WebKit::ProcessLauncher::launchProcess): 33 Merge createService and connectToService into launchProcess. Also make the following changes: 34 - Use mach_port_request_notification to get a notification for when our receive right loses all its senders. 35 This lets us listen for the other process going away before we have a send right for it. 36 - Use xpc_connection_set_event_handler to listen for errors, so we can detect the process going away before 37 we've sent a message to it. 38 39 (WebKit::connectToService): Deleted. 40 (WebKit::createService): Deleted. 41 42 * UIProcess/Network/NetworkProcessProxy.cpp: 43 (WebKit::NetworkProcessProxy::didFinishLaunching): 44 If we failed to launch, call networkProcessCrashedOrFailedToLaunch so we'll unblock any waiting web processes. 45 46 * UIProcess/WebProcessProxy.cpp: 47 (WebKit::WebProcessProxy::didFinishLaunching): 48 Null check the connection and XPC connection before trying to get its pid. 49 1 50 2016-08-11 Brady Eidson <beidson@apple.com> 2 51 -
trunk/Source/WebKit2/Platform/IPC/mac/ConnectionMac.mm
r203387 r204414 480 480 return; 481 481 482 switch (header->msgh_id) { 483 case MACH_NOTIFY_NO_SENDERS: 484 ASSERT(m_isServer); 485 if (!m_sendPort) 486 connectionDidClose(); 487 return; 488 489 case MACH_NOTIFY_SEND_ONCE: 490 return; 491 492 default: 493 break; 494 } 495 482 496 std::unique_ptr<MessageDecoder> decoder = createMessageDecoder(header); 483 497 ASSERT(decoder); … … 501 515 502 516 if (m_sendPort) { 517 mach_port_t previousNotificationPort; 518 mach_port_request_notification(mach_task_self(), m_receivePort, MACH_NOTIFY_NO_SENDERS, 0, MACH_PORT_NULL, MACH_MSG_TYPE_MOVE_SEND_ONCE, &previousNotificationPort); 519 520 if (previousNotificationPort != MACH_PORT_NULL) 521 mach_port_deallocate(mach_task_self(), previousNotificationPort); 522 503 523 initializeDeadNameSource(); 504 524 dispatch_resume(m_deadNameSource); -
trunk/Source/WebKit2/UIProcess/ChildProcessProxy.cpp
r199002 r204414 172 172 ASSERT(!m_connection); 173 173 174 if (IPC::Connection::identifierIsNull(connectionIdentifier)) 175 return; 176 174 177 m_connection = IPC::Connection::createServerConnection(connectionIdentifier, *this); 175 178 #if PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED <= 101000 -
trunk/Source/WebKit2/UIProcess/Launcher/ProcessLauncher.cpp
r203303 r204414 32 32 namespace WebKit { 33 33 34 static WorkQueue& processLauncherWorkQueue()35 {36 37 static WorkQueue& processLauncherWorkQueue = WorkQueue::create("com.apple.WebKit.ProcessLauncher").leakRef();38 return processLauncherWorkQueue;39 }40 41 34 ProcessLauncher::ProcessLauncher(Client* client, const LaunchOptions& launchOptions) 42 35 : m_client(client) 36 , m_weakPtrFactory(this) 43 37 , m_launchOptions(launchOptions) 44 38 , m_processIdentifier(0) 45 39 { 46 40 m_isLaunching = true; 47 48 processLauncherWorkQueue().dispatch([processLauncher = makeRef(*this)]() mutable { 49 processLauncher->launchProcess(); 50 }); 41 launchProcess(); 51 42 } 52 43 -
trunk/Source/WebKit2/UIProcess/Launcher/ProcessLauncher.h
r196661 r204414 24 24 */ 25 25 26 #ifndef WebProcessLauncher_h 27 #define WebProcessLauncher_h 26 #pragma once 28 27 29 28 #include "Connection.h" … … 31 30 #include <wtf/RefPtr.h> 32 31 #include <wtf/Threading.h> 32 #include <wtf/WeakPtr.h> 33 33 #include <wtf/text/StringHash.h> 34 34 #include <wtf/text/WTFString.h> … … 87 87 Client* m_client; 88 88 89 WeakPtrFactory<ProcessLauncher> m_weakPtrFactory; 89 90 const LaunchOptions m_launchOptions; 90 91 bool m_isLaunching; … … 93 94 94 95 } // namespace WebKit 95 96 #endif // WebProcessLauncher_h -
trunk/Source/WebKit2/UIProcess/Launcher/mac/ProcessLauncherMac.mm
r201575 r204414 51 51 namespace WebKit { 52 52 53 typedef void (ProcessLauncher::*DidFinishLaunchingProcessFunction)(pid_t, IPC::Connection::Identifier);54 55 53 static const char* serviceName(const ProcessLauncher::LaunchOptions& launchOptions) 56 54 { … … 84 82 #endif 85 83 } 86 87 static void connectToService(const ProcessLauncher::LaunchOptions& launchOptions, bool forDevelopment, ProcessLauncher* that, DidFinishLaunchingProcessFunction didFinishLaunchingProcessFunction) 88 { 89 // Create a connection to the WebKit XPC service. 90 auto connection = adoptOSObject(xpc_connection_create(serviceName(launchOptions), 0)); 84 85 static NSString *systemDirectoryPath() 86 { 87 static NSString *path = [^{ 88 #if PLATFORM(IOS_SIMULATOR) 89 char *simulatorRoot = getenv("SIMULATOR_ROOT"); 90 return simulatorRoot ? [NSString stringWithFormat:@"%s/System/", simulatorRoot] : @"/System/"; 91 #else 92 return @"/System/"; 93 #endif 94 }() copy]; 95 96 return path; 97 } 98 99 void ProcessLauncher::launchProcess() 100 { 101 auto connection = adoptOSObject(xpc_connection_create(serviceName(m_launchOptions), dispatch_get_main_queue())); 91 102 92 103 uuid_t uuid; … … 112 123 #endif 113 124 114 auto languagesIterator = launchOptions.extraInitializationData.find("OverrideLanguages");115 if (languagesIterator != launchOptions.extraInitializationData.end()) {125 auto languagesIterator = m_launchOptions.extraInitializationData.find("OverrideLanguages"); 126 if (languagesIterator != m_launchOptions.extraInitializationData.end()) { 116 127 auto languages = adoptOSObject(xpc_array_create(nullptr, 0)); 117 128 Vector<String> languageVector; … … 124 135 xpc_connection_set_bootstrap(connection.get(), initializationMessage.get()); 125 136 126 // XPC requires having an event handler, even if it is not used. 127 xpc_connection_set_event_handler(connection.get(), ^(xpc_object_t event) { }); 128 xpc_connection_resume(connection.get()); 129 130 if (shouldLeakBoost(launchOptions)) { 137 if (shouldLeakBoost(m_launchOptions)) { 131 138 auto preBootstrapMessage = adoptOSObject(xpc_dictionary_create(nullptr, nullptr, 0)); 132 139 xpc_dictionary_set_string(preBootstrapMessage.get(), "message-name", "pre-bootstrap"); … … 141 148 mach_port_insert_right(mach_task_self(), listeningPort, listeningPort, MACH_MSG_TYPE_MAKE_SEND); 142 149 150 mach_port_t previousNotificationPort; 151 mach_port_request_notification(mach_task_self(), listeningPort, MACH_NOTIFY_NO_SENDERS, 0, listeningPort, MACH_MSG_TYPE_MAKE_SEND_ONCE, &previousNotificationPort); 152 ASSERT(!previousNotificationPort); 153 143 154 String clientIdentifier; 144 155 #if PLATFORM(MAC) … … 158 169 xpc_dictionary_set_string(bootstrapMessage.get(), "ui-process-name", [[[NSProcessInfo processInfo] processName] UTF8String]); 159 170 160 if (forDevelopment) { 171 bool isWebKitDevelopmentBuild = ![[[[NSBundle bundleWithIdentifier:@"com.apple.WebKit"] bundlePath] stringByDeletingLastPathComponent] hasPrefix:systemDirectoryPath()]; 172 if (isWebKitDevelopmentBuild) { 161 173 xpc_dictionary_set_fd(bootstrapMessage.get(), "stdout", STDOUT_FILENO); 162 174 xpc_dictionary_set_fd(bootstrapMessage.get(), "stderr", STDERR_FILENO); … … 165 177 auto extraInitializationData = adoptOSObject(xpc_dictionary_create(nullptr, nullptr, 0)); 166 178 167 for (const auto& keyValuePair : launchOptions.extraInitializationData)179 for (const auto& keyValuePair : m_launchOptions.extraInitializationData) 168 180 xpc_dictionary_set_string(extraInitializationData.get(), keyValuePair.key.utf8().data(), keyValuePair.value.utf8().data()); 169 181 170 182 xpc_dictionary_set_value(bootstrapMessage.get(), "extra-initialization-data", extraInitializationData.get()); 171 183 172 that->ref(); 173 174 xpc_connection_send_message_with_reply(connection.get(), bootstrapMessage.get(), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(xpc_object_t reply) { 175 xpc_type_t type = xpc_get_type(reply); 176 if (type == XPC_TYPE_ERROR) { 177 // We failed to launch. Release the send right. 178 mach_port_deallocate(mach_task_self(), listeningPort); 179 180 // And the receive right. 181 mach_port_mod_refs(mach_task_self(), listeningPort, MACH_PORT_RIGHT_RECEIVE, -1); 182 183 RunLoop::main().dispatch([protectedThat = RefPtr<ProcessLauncher>(that), didFinishLaunchingProcessFunction]() mutable { 184 (*protectedThat.*didFinishLaunchingProcessFunction)(0, IPC::Connection::Identifier()); 185 }); 186 } else { 187 ASSERT(type == XPC_TYPE_DICTIONARY); 184 auto weakProcessLauncher = m_weakPtrFactory.createWeakPtr(); 185 xpc_connection_set_event_handler(connection.get(), [weakProcessLauncher, listeningPort](xpc_object_t event) { 186 ASSERT(xpc_get_type(event) == XPC_TYPE_ERROR); 187 188 auto processLauncher = weakProcessLauncher.get(); 189 if (!processLauncher) 190 return; 191 192 if (!processLauncher->isLaunching()) 193 return; 194 195 // We failed to launch. Release the send right. 196 mach_port_deallocate(mach_task_self(), listeningPort); 197 198 // And the receive right. 199 mach_port_mod_refs(mach_task_self(), listeningPort, MACH_PORT_RIGHT_RECEIVE, -1); 200 processLauncher->didFinishLaunchingProcess(0, IPC::Connection::Identifier()); 201 }); 202 203 xpc_connection_resume(connection.get()); 204 205 ref(); 206 xpc_connection_send_message_with_reply(connection.get(), bootstrapMessage.get(), dispatch_get_main_queue(), ^(xpc_object_t reply) { 207 // Errors are handled in the event handler. 208 if (xpc_get_type(reply) != XPC_TYPE_ERROR) { 209 ASSERT(xpc_get_type(reply) == XPC_TYPE_DICTIONARY); 188 210 ASSERT(!strcmp(xpc_dictionary_get_string(reply, "message-name"), "process-finished-launching")); 189 211 … … 191 213 pid_t processIdentifier = xpc_connection_get_pid(connection.get()); 192 214 193 // We've finished launching the process, message back to the main run loop. This takes ownership of the connection. 194 RunLoop::main().dispatch([protectedThat = RefPtr<ProcessLauncher>(that), didFinishLaunchingProcessFunction, processIdentifier, listeningPort, connection] { 195 (*protectedThat.*didFinishLaunchingProcessFunction)(processIdentifier, IPC::Connection::Identifier(listeningPort, connection)); 196 }); 215 didFinishLaunchingProcess(processIdentifier, IPC::Connection::Identifier(listeningPort, connection)); 197 216 } 198 217 199 that->deref();218 deref(); 200 219 }); 201 }202 203 static void createService(const ProcessLauncher::LaunchOptions& launchOptions, bool forDevelopment, ProcessLauncher* that, DidFinishLaunchingProcessFunction didFinishLaunchingProcessFunction)204 {205 connectToService(launchOptions, forDevelopment, that, didFinishLaunchingProcessFunction);206 }207 208 static NSString *systemDirectoryPath()209 {210 static NSString *path = [^{211 #if PLATFORM(IOS_SIMULATOR)212 char *simulatorRoot = getenv("SIMULATOR_ROOT");213 return simulatorRoot ? [NSString stringWithFormat:@"%s/System/", simulatorRoot] : @"/System/";214 #else215 return @"/System/";216 #endif217 }() copy];218 219 return path;220 }221 222 void ProcessLauncher::launchProcess()223 {224 bool isWebKitDevelopmentBuild = ![[[[NSBundle bundleWithIdentifier:@"com.apple.WebKit"] bundlePath] stringByDeletingLastPathComponent] hasPrefix:systemDirectoryPath()];225 226 createService(m_launchOptions, isWebKitDevelopmentBuild, this, &ProcessLauncher::didFinishLaunchingProcess);227 220 } 228 221 -
trunk/Source/WebKit2/UIProcess/Network/NetworkProcessProxy.cpp
r203856 r204414 300 300 301 301 if (IPC::Connection::identifierIsNull(connectionIdentifier)) { 302 // FIXME: Do better cleanup here.302 networkProcessCrashedOrFailedToLaunch(); 303 303 return; 304 304 } -
trunk/Source/WebKit2/UIProcess/WebProcessProxy.cpp
r204243 r204414 614 614 615 615 #if PLATFORM(IOS) 616 xpc_connection_t xpcConnection = connection()->xpcConnection(); 617 ASSERT(xpcConnection); 618 m_throttler.didConnectToProcess(xpc_connection_get_pid(xpcConnection)); 616 if (connection()) { 617 if (xpc_connection_t xpcConnection = connection()->xpcConnection()) 618 m_throttler.didConnectToProcess(xpc_connection_get_pid(xpcConnection)); 619 } 619 620 #endif 620 621 }
Note:
See TracChangeset
for help on using the changeset viewer.