⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 285177 in webkit


Ignore:
Timestamp:
Nov 2, 2021, 12:42:06 PM (5 years ago)
Author:
sihui_liu@apple.com
Message:

Terminate unresponsive network process by crashing it
​https://bugs.webkit.org/show_bug.cgi?id=232603

Reviewed by Chris Dumez.

UI process currently kills network process when it does not respond message in some time (network process being
unresponsive). We've found one common case where network process becomes unresponsive is that it is blocked by
some slow operation on the main thread (like file operation in rdar://84511633). To understand what the
operations are and make a fix, we now ask network process to crash itself on IPC thread. In this way, we can get
crash report that includes the call stack of the main thread. To avoid generating too many crash reports, we
only send the crash message to network process when it becomes unresponsive multiple times in a short time
period.

  • Platform/IPC/Connection.cpp:

(IPC::terminateDueToIPCTerminateMessage):
(IPC::Connection::processIncomingMessage):

  • Scripts/webkit/model.py:
  • Scripts/webkit/tests/MessageNames.cpp:

(IPC::description):
(IPC::receiverName):
(IPC::isValidMessageName):

  • Scripts/webkit/tests/MessageNames.h:
  • UIProcess/Network/NetworkProcessProxy.cpp:

(WebKit::shouldTerminateNetworkProcessBySendingMessage):
(WebKit::NetworkProcessProxy::didBecomeUnresponsive):

Location:
trunk/Source/WebKit
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit/ChangeLog

    r285170 r285177  
     12021-11-02  Sihui Liu  <sihui_liu@apple.com>
     2
     3        Terminate unresponsive network process by crashing it
     4        https://bugs.webkit.org/show_bug.cgi?id=232603
     5
     6        Reviewed by Chris Dumez.
     7
     8        UI process currently kills network process when it does not respond message in some time (network process being
     9        unresponsive). We've found one common case where network process becomes unresponsive is that it is blocked by
     10        some slow operation on the main thread (like file operation in rdar://84511633). To understand what the
     11        operations are and make a fix, we now ask network process to crash itself on IPC thread. In this way, we can get
     12        crash report that includes the call stack of the main thread. To avoid generating too many crash reports, we
     13        only send the crash message to network process when it becomes unresponsive multiple times in a short time
     14        period.
     15
     16        * Platform/IPC/Connection.cpp:
     17        (IPC::terminateDueToIPCTerminateMessage):
     18        (IPC::Connection::processIncomingMessage):
     19        * Scripts/webkit/model.py:
     20        * Scripts/webkit/tests/MessageNames.cpp:
     21        (IPC::description):
     22        (IPC::receiverName):
     23        (IPC::isValidMessageName):
     24        * Scripts/webkit/tests/MessageNames.h:
     25        * UIProcess/Network/NetworkProcessProxy.cpp:
     26        (WebKit::shouldTerminateNetworkProcessBySendingMessage):
     27        (WebKit::NetworkProcessProxy::didBecomeUnresponsive):
     28
    1292021-11-02  Kate Cheney  <katherine_cheney@apple.com>
    230
  • trunk/Source/WebKit/Platform/IPC/Connection.cpp

    r285159 r285177  
    4343#if PLATFORM(COCOA)
    4444#include "MachMessage.h"
     45#include "WKCrashReporter.h"
    4546#endif
    4647
    … …  
    752753}
    753754
     755static NEVER_INLINE NO_RETURN_DUE_TO_CRASH void terminateDueToIPCTerminateMessage()
     756{
     757#if PLATFORM(COCOA)
     758    WebKit::logAndSetCrashLogMessage("Receives Terminate message");
     759#else
     760    WTFLogAlways("Receives Terminate message");
     761#endif
     762    CRASH();
     763}
     764
    754765void Connection::processIncomingMessage(std::unique_ptr<Decoder> message)
    755766{
    … …  
    760771        return;
    761772    }
     773
     774    if (message->messageName() == MessageName::Terminate)
     775        return terminateDueToIPCTerminateMessage();
    762776
    763777    if (!MessageReceiveQueueMap::isValidMessage(*message)) {
  • trunk/Source/WebKit/Scripts/webkit/model.py

    r273204 r285177  
    7878    Message('LegacySessionState', [], [], attributes=[BUILTIN_ATTRIBUTE], condition=None),
    7979    Message('SetStreamDestinationID', [], [], attributes=[BUILTIN_ATTRIBUTE], condition=None),
    80     Message('ProcessOutOfStreamMessage', [], [], attributes=[BUILTIN_ATTRIBUTE], condition=None)
     80    Message('ProcessOutOfStreamMessage', [], [], attributes=[BUILTIN_ATTRIBUTE], condition=None),
     81    Message('Terminate', [], [], attributes=[BUILTIN_ATTRIBUTE], condition=None),
    8182], condition=None)
    8283
  • trunk/Source/WebKit/Scripts/webkit/tests/MessageNames.cpp

    r283702 r285177  
    157157    case MessageName::SyncMessageReply:
    158158        return "SyncMessageReply";
     159    case MessageName::Terminate:
     160        return "Terminate";
    159161    case MessageName::TestWithSuperclass_TestAsyncMessageReply:
    160162        return "TestWithSuperclass_TestAsyncMessageReply";
    … …  
    259261    case MessageName::SetStreamDestinationID:
    260262    case MessageName::SyncMessageReply:
     263    case MessageName::Terminate:
    261264        return ReceiverName::IPC;
    262265    case MessageName::TestWithSuperclass_TestAsyncMessageReply:
    … …  
    467470    if (messageName == IPC::MessageName::SyncMessageReply)
    468471        return true;
     472    if (messageName == IPC::MessageName::Terminate)
     473        return true;
    469474#if ENABLE(TEST_FEATURE)
    470475    if (messageName == IPC::MessageName::TestWithSuperclass_TestAsyncMessageReply)
  • trunk/Source/WebKit/Scripts/webkit/tests/MessageNames.h

    r279221 r285177  
    108108    , SetStreamDestinationID
    109109    , SyncMessageReply
     110    , Terminate
    110111    , TestWithSuperclass_TestAsyncMessageReply
    111112    , TestWithSuperclass_TestAsyncMessageWithConnectionReply
  • trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp

    r285121 r285177  
    8888
    8989static constexpr Seconds networkProcessResponsivenessTimeout = 6_s;
     90static constexpr int unresponsivenessCountLimit = 3;
     91static constexpr Seconds unresponsivenessCheckPeriod = 15_s;
    9092
    9193static HashSet<NetworkProcessProxy*>& networkProcessesSet()
    … …  
    9496    static NeverDestroyed<HashSet<NetworkProcessProxy*>> set;
    9597    return set;
     98}
     99
     100static bool shouldTerminateNetworkProcessBySendingMessage()
     101{
     102    static WallTime unresponsivenessPeriodStartTime = WallTime::now();
     103    static int unresponsivenessCountDuringThisPeriod = 0;
     104    auto now = WallTime::now();
     105
     106    if (now - unresponsivenessPeriodStartTime > unresponsivenessCheckPeriod) {
     107        unresponsivenessCountDuringThisPeriod = 1;
     108        unresponsivenessPeriodStartTime = now;
     109        return false;
     110    }
     111
     112    ++unresponsivenessCountDuringThisPeriod;
     113    if (unresponsivenessCountDuringThisPeriod >= unresponsivenessCountLimit)
     114        return true;
     115
     116    return false;
    96117}
    97118
    … …  
    129150{
    130151    RELEASE_LOG_ERROR(Process, "NetworkProcessProxy::didBecomeUnresponsive: NetworkProcess with PID %d became unresponsive, terminating it", processIdentifier());
     152
     153    // Let network process terminates itself and generate crash report for investigation of hangs.
     154    // We currently only do this when network process becomes unresponsive multiple times in a short
     155    // time period to avoid generating too many crash reports with same back trace on user's device.
     156    if (shouldTerminateNetworkProcessBySendingMessage()) {
     157        sendMessage(makeUniqueRef<IPC::Encoder>(IPC::MessageName::Terminate, 0), { });
     158        RunLoop::main().dispatchAfter(1_s, [weakThis = WeakPtr { *this }] () mutable {
     159            if (weakThis)
     160                weakThis->terminate();
     161        });
     162        return;
     163    }
     164
    131165    terminate();
    132166}
Note: See TracChangeset for help on using the changeset viewer.