Changeset 295707 in webkit


Ignore:
Timestamp:
Jun 21, 2022 6:05:31 PM (2 years ago)
Author:
Matt Woodrow
Message:

ConnectionCocoa doesn't receive disconnect notifications before the client has finished initialising
https://bugs.webkit.org/show_bug.cgi?id=241666

Reviewed by Kimmo Kinnunen.

Adds a MACH_NOTIFY_NO_SENDERS notification to the receive port of a server-side Connection object, so that
we can receive notifications if we fail to initialize the client side of the connection.
This gets removed again once the client side initialization completes, since we already have handling for
disconnections from that point onwards.

The test WebProcessTerminationAfterTooManyGPUProcessCrashes would hang in case the GPU Process would be
restarted and the test would terminate it before the connection was fully established, before the WebContent
process would receive the send right. The test is written in such a way that it is expected is that the GPUP
kill happens only after the connection has been re-established and the audio is playing.

  • Source/WebKit/Platform/IPC/cocoa/ConnectionCocoa.mm:

(IPC::requestNoSenderNotifications):
(IPC::clearNoSenderNotifications):
(IPC::Connection::open):
(IPC::Connection::receiveSourceEventHandler):

  • Tools/TestWebKitAPI/Tests/WebKitCocoa/GPUProcess.mm:

(TEST):

Adds some early returns for failure cases, so that we don't call kill(0, 9).

Canonical link: https://commits.webkit.org/251712@main

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit/Platform/IPC/cocoa/ConnectionCocoa.mm

    r295666 r295707  
    189189}
    190190
     191static void requestNoSenderNotifications(mach_port_t port, mach_port_t notify)
     192{
     193    mach_port_t previousNotificationPort = MACH_PORT_NULL;
     194    auto kr = mach_port_request_notification(mach_task_self(), port, MACH_NOTIFY_NO_SENDERS, 0, notify, MACH_MSG_TYPE_MAKE_SEND_ONCE, &previousNotificationPort);
     195    ASSERT(kr == KERN_SUCCESS);
     196    if (kr != KERN_SUCCESS) {
     197        // If mach_port_request_notification fails, 'previousNotificationPort' will be uninitialized.
     198        LOG_ERROR("mach_port_request_notification failed: (%x) %s", kr, mach_error_string(kr));
     199    } else
     200        deallocateSendRightSafely(previousNotificationPort);
     201}
     202
     203static void requestNoSenderNotifications(mach_port_t port)
     204{
     205    requestNoSenderNotifications(port, port);
     206}
     207
     208static void clearNoSenderNotifications(mach_port_t port)
     209{
     210    requestNoSenderNotifications(port, MACH_PORT_NULL);
     211}
     212
    191213bool Connection::open()
    192214{
     
    240262        mach_port_mod_refs(mach_task_self(), receivePort, MACH_PORT_RIGHT_RECEIVE, -1);
    241263    });
     264    // Disconnections are normally handled by DISPATCH_MACH_SEND_DEAD on the m_sendSource, but that's not
     265    // initialized until we receive the connection message from the client, so we need to request MACH_NOTIFY_NO_SENDERS
     266    // on the receiving port until then.
     267    if (m_isServer)
     268        requestNoSenderNotifications(m_receivePort);
    242269
    243270    m_connectionQueue->dispatch([strongRef = Ref { *this }, this] {
     
    584611        if (m_sendPort) {
    585612            ASSERT(MACH_PORT_VALID(m_receivePort));
    586             mach_port_t previousNotificationPort = MACH_PORT_NULL;
    587             auto kr = mach_port_request_notification(mach_task_self(), m_receivePort, MACH_NOTIFY_NO_SENDERS, 0, MACH_PORT_NULL, MACH_MSG_TYPE_MOVE_SEND_ONCE, &previousNotificationPort);
    588             ASSERT(kr == KERN_SUCCESS);
    589             if (kr != KERN_SUCCESS) {
    590                 // If mach_port_request_notification fails, 'previousNotificationPort' will be uninitialized.
    591                 LOG_ERROR("mach_port_request_notification failed: (%x) %s", kr, mach_error_string(kr));
    592                 previousNotificationPort = MACH_PORT_NULL;
    593             }
    594 
    595             if (previousNotificationPort != MACH_PORT_NULL)
    596                 deallocateSendRightSafely(previousNotificationPort);
     613            clearNoSenderNotifications(m_receivePort);
    597614
    598615            initializeSendSource();
  • trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/GPUProcess.mm

    r295433 r295707  
    116116}
    117117
    118 // FIXME: Re-enable after webkit.org/b/240692 is resolved
    119 #if (PLATFORM(IOS))
    120 TEST(GPUProcess, DISABLED_WebProcessTerminationAfterTooManyGPUProcessCrashes)
    121 #else
    122118TEST(GPUProcess, WebProcessTerminationAfterTooManyGPUProcessCrashes)
    123 #endif
    124119{
    125120    auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
     
    161156    while ((![processPool _gpuProcessIdentifier] || [processPool _gpuProcessIdentifier] == gpuProcessPID) && timeout++ < 100)
    162157        TestWebKitAPI::Util::sleep(0.1);
    163     EXPECT_NE([processPool _gpuProcessIdentifier], 0);
    164     EXPECT_NE([processPool _gpuProcessIdentifier], gpuProcessPID);
     158    ASSERT_NE([processPool _gpuProcessIdentifier], 0);
     159    ASSERT_NE([processPool _gpuProcessIdentifier], gpuProcessPID);
    165160    gpuProcessPID = [processPool _gpuProcessIdentifier];
    166161
     
    175170    while ((![processPool _gpuProcessIdentifier] || [processPool _gpuProcessIdentifier] == gpuProcessPID) && timeout++ < 100)
    176171        TestWebKitAPI::Util::sleep(0.1);
    177     EXPECT_NE([processPool _gpuProcessIdentifier], 0);
    178     EXPECT_NE([processPool _gpuProcessIdentifier], gpuProcessPID);
     172    ASSERT_NE([processPool _gpuProcessIdentifier], 0);
     173    ASSERT_NE([processPool _gpuProcessIdentifier], gpuProcessPID);
    179174    gpuProcessPID = [processPool _gpuProcessIdentifier];
    180175
Note: See TracChangeset for help on using the changeset viewer.