Changeset 202723 in webkit


Ignore:
Timestamp:
Jun 30, 2016 6:29:47 PM (8 years ago)
Author:
Chris Dumez
Message:

[iOS] WebContent processes do not exit promptly
https://bugs.webkit.org/show_bug.cgi?id=159301
<rdar://problem/26965488>

Reviewed by Anders Carlsson.

WebContent processes do not exit promptly, they hang around for 10 seconds
until the watchdog forcefully calls exit().

This patch addresses the issue by asking XPC to exit when clean. It also
fixes 2 XPC transactions that were leaking so that XPC can become clean.

  • DatabaseProcess/EntryPoint/mac/XPCService/DatabaseServiceEntryPoint.mm:

(DatabaseServiceInitializer):

  • NetworkProcess/EntryPoint/mac/XPCService/NetworkServiceEntryPoint.mm:

(NetworkServiceInitializer):

  • PluginProcess/EntryPoint/mac/XPCService/PluginServiceEntryPoint.mm:

(PluginServiceInitializer):

  • WebProcess/EntryPoint/mac/XPCService/WebContentServiceEntryPoint.mm:

(WebContentServiceInitializer):
Add extra priorityBoostMessage parameter which is then passed along to
ChildProcess via initialization parameters. ChildProcess is now in
charge of retaining the message for as long as it needs the priority
boost. In particular, ChildProcess now takes care of releasing the
boost message before existing to avoid leaking an XPC transaction.

  • Shared/ChildProcess.cpp:

(WebKit::ChildProcess::initialize):
Retain priorityBoostMessage as a data member.

(WebKit::ChildProcess::stopRunLoop):
(WebKit::ChildProcess::platformStopRunLoop):

  • Shared/ios/ChildProcessIOS.mm:

(WebKit::ChildProcess::platformStopRunLoop):
On iOS, call XPCServiceExit() to exit instead of RunLoop::main().stop()
which did not work.

  • Shared/ChildProcess.h:
  • Shared/EntryPointUtilities/mac/XPCService/XPCServiceEntryPoint.h:

(WebKit::XPCServiceInitializer):
Set priorityBoostMessage on ChildProcessInitializationParameters.

  • Shared/EntryPointUtilities/mac/XPCService/XPCServiceEntryPoint.mm:

(WebKit::XPCServiceExit):
Add XPCServiceExit() function which destroys the priority boost
message, calls xpc_transaction_end() to balance the
xpc_transaction_begin() in XPCServiceInitializer() and then call
xpc_transaction_exit_clean() to ask XPC to exit when clean.

  • Shared/EntryPointUtilities/mac/XPCService/XPCServiceMain.mm:

(WebKit::XPCServiceEventHandler):
Leaking the "pre-bootstrap" event for priority boosting would cause us to
leak an XPC transaction, which would prevent XPC from becoming clean and
exiting. Instead, we now pass it along to the initialization function.
We then pass it to ChildProcess which manages the lifetime of this message
instead of leaking it.

Location:
trunk/Source
Files:
12 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WTF/wtf/spi/darwin/XPCSPI.h

    r194318 r202723  
    124124EXTERN_C const char* xpc_string_get_string_ptr(xpc_object_t);
    125125EXTERN_C void xpc_transaction_begin(void);
     126EXTERN_C void xpc_transaction_end(void);
     127EXTERN_C void xpc_transaction_exit_clean(void);
    126128EXTERN_C void xpc_track_activity(void);
    127129
  • trunk/Source/WebKit2/ChangeLog

    r202700 r202723  
     12016-06-30  Chris Dumez  <cdumez@apple.com>
     2
     3        [iOS] WebContent processes do not exit promptly
     4        https://bugs.webkit.org/show_bug.cgi?id=159301
     5        <rdar://problem/26965488>
     6
     7        Reviewed by Anders Carlsson.
     8
     9        WebContent processes do not exit promptly, they hang around for 10 seconds
     10        until the watchdog forcefully calls exit().
     11
     12        This patch addresses the issue by asking XPC to exit when clean. It also
     13        fixes 2 XPC transactions that were leaking so that XPC can become clean.
     14
     15        * DatabaseProcess/EntryPoint/mac/XPCService/DatabaseServiceEntryPoint.mm:
     16        (DatabaseServiceInitializer):
     17        * NetworkProcess/EntryPoint/mac/XPCService/NetworkServiceEntryPoint.mm:
     18        (NetworkServiceInitializer):
     19        * PluginProcess/EntryPoint/mac/XPCService/PluginServiceEntryPoint.mm:
     20        (PluginServiceInitializer):
     21        * WebProcess/EntryPoint/mac/XPCService/WebContentServiceEntryPoint.mm:
     22        (WebContentServiceInitializer):
     23        Add extra priorityBoostMessage parameter which is then passed along to
     24        ChildProcess via initialization parameters. ChildProcess is now in
     25        charge of retaining the message for as long as it needs the priority
     26        boost. In particular, ChildProcess now takes care of releasing the
     27        boost message before existing to avoid leaking an XPC transaction.
     28
     29        * Shared/ChildProcess.cpp:
     30        (WebKit::ChildProcess::initialize):
     31        Retain priorityBoostMessage as a data member.
     32
     33        (WebKit::ChildProcess::stopRunLoop):
     34        (WebKit::ChildProcess::platformStopRunLoop):
     35        * Shared/ios/ChildProcessIOS.mm:
     36        (WebKit::ChildProcess::platformStopRunLoop):
     37        On iOS, call XPCServiceExit() to exit instead of RunLoop::main().stop()
     38        which did not work.
     39
     40        * Shared/ChildProcess.h:
     41        * Shared/EntryPointUtilities/mac/XPCService/XPCServiceEntryPoint.h:
     42        (WebKit::XPCServiceInitializer):
     43        Set priorityBoostMessage on ChildProcessInitializationParameters.
     44
     45        * Shared/EntryPointUtilities/mac/XPCService/XPCServiceEntryPoint.mm:
     46        (WebKit::XPCServiceExit):
     47        Add XPCServiceExit() function which destroys the priority boost
     48        message, calls xpc_transaction_end() to balance the
     49        xpc_transaction_begin() in XPCServiceInitializer() and then call
     50        xpc_transaction_exit_clean() to ask XPC to exit when clean.
     51
     52        * Shared/EntryPointUtilities/mac/XPCService/XPCServiceMain.mm:
     53        (WebKit::XPCServiceEventHandler):
     54        Leaking the "pre-bootstrap" event for priority boosting would cause us to
     55        leak an XPC transaction, which would prevent XPC from becoming clean and
     56        exiting. Instead, we now pass it along to the initialization function.
     57        We then pass it to ChildProcess which manages the lifetime of this message
     58        instead of leaking it.
     59
    1602016-06-30  Brian Burg  <bburg@apple.com>
    261
  • trunk/Source/WebKit2/DatabaseProcess/EntryPoint/mac/XPCService/DatabaseServiceEntryPoint.mm

    r200628 r202723  
    3737using namespace WebKit;
    3838
    39 extern "C" WK_EXPORT void DatabaseServiceInitializer(xpc_connection_t connection, xpc_object_t initializerMessage);
     39extern "C" WK_EXPORT void DatabaseServiceInitializer(xpc_connection_t connection, xpc_object_t initializerMessage, xpc_object_t priorityBoostMessage);
    4040
    41 void DatabaseServiceInitializer(xpc_connection_t connection, xpc_object_t initializerMessage)
     41void DatabaseServiceInitializer(xpc_connection_t connection, xpc_object_t initializerMessage, xpc_object_t priorityBoostMessage)
    4242{
    4343#if HAVE(OS_ACTIVITY)
     
    4848#endif
    4949
    50     XPCServiceInitializer<DatabaseProcess, XPCServiceInitializerDelegate>(adoptOSObject(connection), initializerMessage);
     50    XPCServiceInitializer<DatabaseProcess, XPCServiceInitializerDelegate>(adoptOSObject(connection), initializerMessage, priorityBoostMessage);
    5151
    5252#if HAVE(OS_ACTIVITY)
  • trunk/Source/WebKit2/NetworkProcess/EntryPoint/mac/XPCService/NetworkServiceEntryPoint.mm

    r200631 r202723  
    4949using namespace WebKit;
    5050
    51 extern "C" WK_EXPORT void NetworkServiceInitializer(xpc_connection_t connection, xpc_object_t initializerMessage);
     51extern "C" WK_EXPORT void NetworkServiceInitializer(xpc_connection_t connection, xpc_object_t initializerMessage, xpc_object_t priorityBoostMessage);
    5252
    53 void NetworkServiceInitializer(xpc_connection_t connection, xpc_object_t initializerMessage)
     53void NetworkServiceInitializer(xpc_connection_t connection, xpc_object_t initializerMessage, xpc_object_t priorityBoostMessage)
    5454{
    5555    // Remove the SecItemShim from the DYLD_INSERT_LIBRARIES environment variable so any processes spawned by
     
    6464#endif
    6565
    66     XPCServiceInitializer<NetworkProcess, NetworkServiceInitializerDelegate>(adoptOSObject(connection), initializerMessage);
     66    XPCServiceInitializer<NetworkProcess, NetworkServiceInitializerDelegate>(adoptOSObject(connection), initializerMessage, priorityBoostMessage);
    6767
    6868#if HAVE(OS_ACTIVITY)
  • trunk/Source/WebKit2/PluginProcess/EntryPoint/mac/XPCService/PluginServiceEntryPoint.mm

    r200631 r202723  
    7070#endif // ENABLE(NETSCAPE_PLUGIN_API)
    7171
    72 extern "C" WK_EXPORT void PluginServiceInitializer(xpc_connection_t connection, xpc_object_t initializerMessage);
     72extern "C" WK_EXPORT void PluginServiceInitializer(xpc_connection_t connection, xpc_object_t initializerMessage, xpc_object_t priorityBoostMessage);
    7373
    74 void PluginServiceInitializer(xpc_connection_t connection, xpc_object_t initializerMessage)
     74void PluginServiceInitializer(xpc_connection_t connection, xpc_object_t initializerMessage, xpc_object_t priorityBoostMessage)
    7575{
    7676#if ENABLE(NETSCAPE_PLUGIN_API)
     
    8888#endif
    8989
    90     XPCServiceInitializer<PluginProcess, PluginServiceInitializerDelegate>(adoptOSObject(connection), initializerMessage);
     90    XPCServiceInitializer<PluginProcess, PluginServiceInitializerDelegate>(adoptOSObject(connection), initializerMessage, priorityBoostMessage);
    9191
    9292#if HAVE(OS_ACTIVITY)
  • trunk/Source/WebKit2/Shared/ChildProcess.cpp

    r202611 r202723  
    6464{
    6565    platformInitialize();
     66
     67#if PLATFORM(COCOA)
     68    m_priorityBoostMessage = parameters.priorityBoostMessage;
     69#endif
    6670
    6771    initializeProcess(parameters);
     
    159163void ChildProcess::stopRunLoop()
    160164{
     165    platformStopRunLoop();
     166}
     167
     168#if !PLATFORM(IOS)
     169void ChildProcess::platformStopRunLoop()
     170{
    161171    RunLoop::main().stop();
    162172}
     173#endif
    163174
    164175void ChildProcess::terminate()
  • trunk/Source/WebKit2/Shared/ChildProcess.h

    r202611 r202723  
    4646    IPC::Connection::Identifier connectionIdentifier;
    4747    HashMap<String, String> extraInitializationData;
     48#if PLATFORM(COCOA)
     49    OSObjectPtr<xpc_object_t> priorityBoostMessage;
     50#endif
    4851};
    4952
     
    111114
    112115    void platformInitialize();
     116    void platformStopRunLoop();
    113117
    114118    // The timeout, in seconds, before this process will be terminated if termination
     
    126130
    127131    UserActivity m_processSuppressionDisabled;
     132
     133#if PLATFORM(COCOA)
     134    OSObjectPtr<xpc_object_t> m_priorityBoostMessage;
     135#endif
    128136};
    129137
  • trunk/Source/WebKit2/Shared/EntryPointUtilities/mac/XPCService/XPCServiceEntryPoint.h

    r195985 r202723  
    6868
    6969template<typename XPCServiceType, typename XPCServiceInitializerDelegateType>
    70 void XPCServiceInitializer(OSObjectPtr<xpc_connection_t> connection, xpc_object_t initializerMessage)
     70void XPCServiceInitializer(OSObjectPtr<xpc_connection_t> connection, xpc_object_t initializerMessage, xpc_object_t priorityBoostMessage)
    7171{
    7272    XPCServiceInitializerDelegateType delegate(WTFMove(connection), initializerMessage);
     
    8282
    8383    ChildProcessInitializationParameters parameters;
     84    if (priorityBoostMessage)
     85        parameters.priorityBoostMessage = adoptOSObject(xpc_retain(priorityBoostMessage));
     86
    8487    if (!delegate.getConnectionIdentifier(parameters.connectionIdentifier))
    8588        exit(EXIT_FAILURE);
     
    102105}
    103106
     107void XPCServiceExit(OSObjectPtr<xpc_object_t>&& priorityBoostMessage);
     108
    104109} // namespace WebKit
    105110
  • trunk/Source/WebKit2/Shared/EntryPointUtilities/mac/XPCService/XPCServiceEntryPoint.mm

    r190257 r202723  
    121121}
    122122
     123void XPCServiceExit(OSObjectPtr<xpc_object_t>&& priorityBoostMessage)
     124{
     125    // Make sure to destroy the priority boost message to avoid leaking a transaction.
     126    priorityBoostMessage = nullptr;
     127    // Balances the xpc_transaction_begin() in XPCServiceInitializer.
     128    xpc_transaction_end();
     129    xpc_transaction_exit_clean();
     130}
     131
    123132} // namespace WebKit
  • trunk/Source/WebKit2/Shared/EntryPointUtilities/mac/XPCService/XPCServiceMain.mm

    r195795 r202723  
    3535static void XPCServiceEventHandler(xpc_connection_t peer)
    3636{
     37    static xpc_object_t priorityBoostMessage = nullptr;
     38
    3739    xpc_connection_set_target_queue(peer, dispatch_get_main_queue());
    3840    xpc_connection_set_event_handler(peer, ^(xpc_object_t event) {
     
    5052                CFStringRef entryPointFunctionName = (CFStringRef)CFBundleGetValueForInfoDictionaryKey(CFBundleGetMainBundle(), CFSTR("WebKitEntryPoint"));
    5153
    52                 typedef void (*InitializerFunction)(xpc_connection_t, xpc_object_t);
     54                typedef void (*InitializerFunction)(xpc_connection_t, xpc_object_t, xpc_object_t);
    5355                InitializerFunction initializerFunctionPtr = reinterpret_cast<InitializerFunction>(CFBundleGetFunctionPointerForName(webKitBundle, entryPointFunctionName));
    5456                if (!initializerFunctionPtr) {
     
    6971                    dup2(fd, STDERR_FILENO);
    7072
    71                 initializerFunctionPtr(peer, event);
     73                initializerFunctionPtr(peer, event, priorityBoostMessage);
     74                if (priorityBoostMessage)
     75                    xpc_release(priorityBoostMessage);
    7276            }
    7377
    7478            // Leak a boost onto the NetworkProcess.
    75             if (!strcmp(xpc_dictionary_get_string(event, "message-name"), "pre-bootstrap"))
    76                 xpc_retain(event);
     79            if (!strcmp(xpc_dictionary_get_string(event, "message-name"), "pre-bootstrap")) {
     80                assert(!priorityBoostMessage);
     81                priorityBoostMessage = xpc_retain(event);
     82            }
    7783        }
    7884    });
  • trunk/Source/WebKit2/Shared/ios/ChildProcessIOS.mm

    r193783 r202723  
    3232#import "SandboxInitializationParameters.h"
    3333#import "WebKitSystemInterface.h"
     34#import "XPCServiceEntryPoint.h"
    3435#import <WebCore/FileSystem.h>
    3536#import <WebCore/FloatingPointEnvironment.h>
     
    115116}
    116117
     118void ChildProcess::platformStopRunLoop()
     119{
     120    XPCServiceExit(WTFMove(m_priorityBoostMessage));
     121}
     122
    117123} // namespace WebKit
    118124
  • trunk/Source/WebKit2/WebProcess/EntryPoint/mac/XPCService/WebContentServiceEntryPoint.mm

    r200631 r202723  
    4444using namespace WebKit;
    4545
    46 extern "C" WK_EXPORT void WebContentServiceInitializer(xpc_connection_t connection, xpc_object_t initializerMessage);
     46extern "C" WK_EXPORT void WebContentServiceInitializer(xpc_connection_t connection, xpc_object_t initializerMessage, xpc_object_t priorityBoostMessage);
    4747
    48 void WebContentServiceInitializer(xpc_connection_t connection, xpc_object_t initializerMessage)
     48void WebContentServiceInitializer(xpc_connection_t connection, xpc_object_t initializerMessage, xpc_object_t priorityBoostMessage)
    4949{
    5050    // Remove the WebProcessShim from the DYLD_INSERT_LIBRARIES environment variable so any processes spawned by
     
    6464#endif // PLATFORM(IOS)
    6565
    66     XPCServiceInitializer<WebProcess, XPCServiceInitializerDelegate>(adoptOSObject(connection), initializerMessage);
     66    XPCServiceInitializer<WebProcess, XPCServiceInitializerDelegate>(adoptOSObject(connection), initializerMessage, priorityBoostMessage);
    6767
    6868#if HAVE(OS_ACTIVITY)
Note: See TracChangeset for help on using the changeset viewer.