Diff
Modified: trunk/Source/WTF/ChangeLog (232175 => 232176)
--- trunk/Source/WTF/ChangeLog 2018-05-25 00:25:23 UTC (rev 232175)
+++ trunk/Source/WTF/ChangeLog 2018-05-25 00:52:13 UTC (rev 232176)
@@ -1,3 +1,18 @@
+2018-05-24 Carlos Alberto Lopez Perez <[email protected]>
+
+ [GTK][WPE] Memory pressure monitor doesn't reliable notify all the subprocesses
+ https://bugs.webkit.org/show_bug.cgi?id=184261
+
+ Reviewed by Carlos Garcia Campos.
+
+ Receive the memory pressure notifications from the UIProcess memory monitor via WebKit IPC.
+
+ * wtf/MemoryPressureHandler.h:
+ * wtf/linux/MemoryPressureHandlerLinux.cpp:
+ (WTF::MemoryPressureHandler::triggerMemoryPressureEvent):
+ (WTF::MemoryPressureHandler::install):
+ (WTF::MemoryPressureHandler::uninstall):
+
2018-05-24 Jiewen Tan <[email protected]>
Adopt SecKeyProxy SPI in certificate based challenge response code
Modified: trunk/Source/WTF/wtf/MemoryPressureHandler.h (232175 => 232176)
--- trunk/Source/WTF/wtf/MemoryPressureHandler.h 2018-05-25 00:25:23 UTC (rev 232175)
+++ trunk/Source/WTF/wtf/MemoryPressureHandler.h 2018-05-25 00:52:13 UTC (rev 232176)
@@ -69,6 +69,10 @@
WTF_EXPORT_PRIVATE void setShouldUsePeriodicMemoryMonitor(bool);
+#if OS(LINUX)
+ WTF_EXPORT_PRIVATE void triggerMemoryPressureEvent(bool isCritical);
+#endif
+
void setMemoryKillCallback(WTF::Function<void()>&& function) { m_memoryKillCallback = WTFMove(function); }
void setMemoryPressureStatusChangedCallback(WTF::Function<void(bool)>&& function) { m_memoryPressureStatusChangedCallback = WTFMove(function); }
void setDidExceedInactiveLimitWhileActiveCallback(WTF::Function<void()>&& function) { m_didExceedInactiveLimitWhileActiveCallback = WTFMove(function); }
@@ -88,10 +92,6 @@
}
void setUnderMemoryPressure(bool);
-#if OS(LINUX)
- void setMemoryPressureMonitorHandle(int fd);
-#endif
-
class ReliefLogger {
public:
explicit ReliefLogger(const char *log)
@@ -169,26 +169,6 @@
void doesExceedInactiveLimitWhileActive();
void doesNotExceedInactiveLimitWhileActive();
-#if OS(LINUX)
- class EventFDPoller {
- WTF_MAKE_NONCOPYABLE(EventFDPoller); WTF_MAKE_FAST_ALLOCATED;
- public:
- EventFDPoller(int fd, WTF::Function<void ()>&& notifyHandler);
- ~EventFDPoller();
-
- private:
- void readAndNotify() const;
-
- std::optional<int> m_fd;
- WTF::Function<void ()> m_notifyHandler;
-#if USE(GLIB)
- GRefPtr<GSource> m_source;
-#else
- RefPtr<Thread> m_thread;
-#endif
- };
-#endif
-
WebsamProcessState m_processState { WebsamProcessState::Inactive };
unsigned m_pageCount { 0 };
@@ -213,13 +193,8 @@
#endif
#if OS(LINUX)
- std::optional<int> m_eventFD;
- std::optional<int> m_pressureLevelFD;
- std::unique_ptr<EventFDPoller> m_eventFDPoller;
RunLoop::Timer<MemoryPressureHandler> m_holdOffTimer;
void holdOffTimerFired();
- void logErrorAndCloseFDs(const char* error);
- bool tryEnsureEventFD();
#endif
};
Modified: trunk/Source/WTF/wtf/linux/MemoryPressureHandlerLinux.cpp (232175 => 232176)
--- trunk/Source/WTF/wtf/linux/MemoryPressureHandlerLinux.cpp 2018-05-25 00:25:23 UTC (rev 232175)
+++ trunk/Source/WTF/wtf/linux/MemoryPressureHandlerLinux.cpp 2018-05-25 00:52:13 UTC (rev 232176)
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2011, 2012 Apple Inc. All Rights Reserved.
* Copyright (C) 2014 Raspberry Pi Foundation. All Rights Reserved.
+ * Copyright (C) 2018 Igalia S.L.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -29,12 +30,7 @@
#if OS(LINUX)
-#include <errno.h>
-#include <fcntl.h>
#include <malloc.h>
-#include <sys/eventfd.h>
-#include <sys/stat.h>
-#include <sys/types.h>
#include <unistd.h>
#include <wtf/MainThread.h>
#include <wtf/MemoryFootprint.h>
@@ -41,11 +37,6 @@
#include <wtf/linux/CurrentProcessMemoryStatus.h>
#include <wtf/text/WTFString.h>
-#if USE(GLIB)
-#include <glib-unix.h>
-#include <wtf/glib/RunLoopSourcePriority.h>
-#endif
-
#define LOG_CHANNEL_PREFIX Log
namespace WTF {
@@ -63,189 +54,34 @@
static const size_t s_minimumBytesFreedToUseMinimumHoldOffTime = 1 * MB;
static const unsigned s_holdOffMultiplier = 20;
-static const char* s_cgroupMemoryPressureLevel = "/sys/fs/cgroup/memory/memory.pressure_level";
-static const char* s_cgroupEventControl = "/sys/fs/cgroup/memory/cgroup.event_control";
-
-#if USE(GLIB)
-typedef struct {
- GSource source;
- gpointer fdTag;
- GIOCondition condition;
-} EventFDSource;
-
-static const unsigned eventFDSourceCondition = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL;
-
-static GSourceFuncs eventFDSourceFunctions = {
- nullptr, // prepare
- nullptr, // check
- // dispatch
- [](GSource* source, GSourceFunc callback, gpointer userData) -> gboolean
- {
- EventFDSource* eventFDSource = reinterpret_cast<EventFDSource*>(source);
- unsigned events = g_source_query_unix_fd(source, eventFDSource->fdTag) & eventFDSourceCondition;
- if (events & G_IO_HUP || events & G_IO_ERR || events & G_IO_NVAL)
- return G_SOURCE_REMOVE;
-
- gboolean returnValue = G_SOURCE_CONTINUE;
- if (events & G_IO_IN)
- returnValue = callback(userData);
- g_source_set_ready_time(source, -1);
- return returnValue;
- },
- nullptr, // finalize
- nullptr, // closure_callback
- nullptr, // closure_marshall
-};
-#endif
-
-MemoryPressureHandler::EventFDPoller::EventFDPoller(int fd, WTF::Function<void ()>&& notifyHandler)
- : m_fd(fd)
- , m_notifyHandler(WTFMove(notifyHandler))
+void MemoryPressureHandler::triggerMemoryPressureEvent(bool isCritical)
{
-#if USE(GLIB)
- m_source = adoptGRef(g_source_new(&eventFDSourceFunctions, sizeof(EventFDSource)));
- g_source_set_priority(m_source.get(), RunLoopSourcePriority::MemoryPressureHandlerTimer);
- g_source_set_name(m_source.get(), "WTF: MemoryPressureHandler");
- if (!g_unix_set_fd_nonblocking(m_fd.value(), TRUE, nullptr)) {
- LOG(MemoryPressure, "Failed to set eventfd nonblocking");
+ if (!m_installed)
return;
- }
- EventFDSource* eventFDSource = reinterpret_cast<EventFDSource*>(m_source.get());
- eventFDSource->fdTag = g_source_add_unix_fd(m_source.get(), m_fd.value(), static_cast<GIOCondition>(eventFDSourceCondition));
- g_source_set_callback(m_source.get(), [](gpointer userData) -> gboolean {
- static_cast<EventFDPoller*>(userData)->readAndNotify();
- return G_SOURCE_REMOVE;
- }, this, nullptr);
- g_source_attach(m_source.get(), nullptr);
-#else
- m_thread = Thread::create("WTF: MemoryPressureHandler",
- [this] {
- readAndNotify();
- });
-#endif
-}
+ if (ReliefLogger::loggingEnabled())
+ LOG(MemoryPressure, "Got memory pressure notification (%s)", isCritical ? "critical" : "non-critical");
-MemoryPressureHandler::EventFDPoller::~EventFDPoller()
-{
- m_fd = std::nullopt;
-#if USE(GLIB)
- g_source_destroy(m_source.get());
-#else
- m_thread->detach();
-#endif
-}
+ setUnderMemoryPressure(true);
-static inline bool isFatalReadError(int error)
-{
-#if USE(GLIB)
- // We don't really need to read the buffer contents, if the poller
- // notified us, but read would block or is no longer available, is
- // enough to trigger the memory pressure handler.
- return error != EAGAIN && error != EWOULDBLOCK;
-#else
- return true;
-#endif
-}
+ if (isMainThread())
+ respondToMemoryPressure(isCritical ? Critical::Yes : Critical::No);
+ else
+ RunLoop::main().dispatch([this, isCritical] {
+ respondToMemoryPressure(isCritical ? Critical::Yes : Critical::No);
+ });
-void MemoryPressureHandler::EventFDPoller::readAndNotify() const
-{
- if (!m_fd) {
- LOG(MemoryPressure, "Invalidate eventfd.");
- return;
- }
+ if (ReliefLogger::loggingEnabled() && isUnderMemoryPressure())
+ LOG(MemoryPressure, "System is no longer under memory pressure.");
- uint64_t buffer;
- if (read(m_fd.value(), &buffer, sizeof(buffer)) == -1) {
- if (isFatalReadError(errno)) {
- LOG(MemoryPressure, "Failed to read eventfd.");
- return;
- }
- }
-
- m_notifyHandler();
+ setUnderMemoryPressure(false);
}
-inline void MemoryPressureHandler::logErrorAndCloseFDs(const char* log)
-{
- if (log)
- LOG(MemoryPressure, "%s, error : %m", log);
-
- if (m_eventFD) {
- close(m_eventFD.value());
- m_eventFD = std::nullopt;
- }
- if (m_pressureLevelFD) {
- close(m_pressureLevelFD.value());
- m_pressureLevelFD = std::nullopt;
- }
-}
-
-bool MemoryPressureHandler::tryEnsureEventFD()
-{
- if (m_eventFD)
- return true;
-
- // Try to use cgroups instead.
- int fd = eventfd(0, EFD_CLOEXEC);
- if (fd == -1) {
- LOG(MemoryPressure, "eventfd() failed: %m");
- return false;
- }
- m_eventFD = fd;
-
- fd = open(s_cgroupMemoryPressureLevel, O_CLOEXEC | O_RDONLY);
- if (fd == -1) {
- logErrorAndCloseFDs("Failed to open memory.pressure_level");
- return false;
- }
- m_pressureLevelFD = fd;
-
- fd = open(s_cgroupEventControl, O_CLOEXEC | O_WRONLY);
- if (fd == -1) {
- logErrorAndCloseFDs("Failed to open cgroup.event_control");
- return false;
- }
-
- char line[128] = {0, };
- if (snprintf(line, sizeof(line), "%d %d low", m_eventFD.value(), m_pressureLevelFD.value()) < 0
- || write(fd, line, strlen(line) + 1) < 0) {
- logErrorAndCloseFDs("Failed to write cgroup.event_control");
- close(fd);
- return false;
- }
- close(fd);
-
- return true;
-}
-
void MemoryPressureHandler::install()
{
if (m_installed || m_holdOffTimer.isActive())
return;
- if (!tryEnsureEventFD())
- return;
-
- m_eventFDPoller = std::make_unique<EventFDPoller>(m_eventFD.value(), [this] {
- // FIXME: Current memcg does not provide any way for users to know how serious the memory pressure is.
- // So we assume all notifications from memcg are critical for now. If memcg had better inferfaces
- // to get a detailed memory pressure level in the future, we should update here accordingly.
- bool critical = true;
- if (ReliefLogger::loggingEnabled())
- LOG(MemoryPressure, "Got memory pressure notification (%s)", critical ? "critical" : "non-critical");
-
- setUnderMemoryPressure(critical);
- if (isMainThread())
- respondToMemoryPressure(critical ? Critical::Yes : Critical::No);
- else
- RunLoop::main().dispatch([this, critical] { respondToMemoryPressure(critical ? Critical::Yes : Critical::No); });
- });
-
- if (ReliefLogger::loggingEnabled() && isUnderMemoryPressure())
- LOG(MemoryPressure, "System is no longer under memory pressure.");
-
- setUnderMemoryPressure(false);
m_installed = true;
}
@@ -255,19 +91,7 @@
return;
m_holdOffTimer.stop();
- m_eventFDPoller = nullptr;
- if (m_pressureLevelFD) {
- close(m_pressureLevelFD.value());
- m_pressureLevelFD = std::nullopt;
-
- // Only close the eventFD used for cgroups.
- if (m_eventFD) {
- close(m_eventFD.value());
- m_eventFD = std::nullopt;
- }
- }
-
m_installed = false;
}
@@ -318,11 +142,6 @@
return MemoryUsage {processMemoryUsage(), physical};
}
-void MemoryPressureHandler::setMemoryPressureMonitorHandle(int fd)
-{
- ASSERT(!m_eventFD);
- m_eventFD = fd;
-}
} // namespace WTF
Modified: trunk/Source/WebKit/ChangeLog (232175 => 232176)
--- trunk/Source/WebKit/ChangeLog 2018-05-25 00:25:23 UTC (rev 232175)
+++ trunk/Source/WebKit/ChangeLog 2018-05-25 00:52:13 UTC (rev 232176)
@@ -1,3 +1,82 @@
+2018-05-24 Carlos Alberto Lopez Perez <[email protected]>
+
+ [GTK][WPE] Memory pressure monitor doesn't reliable notify all the subprocesses
+ https://bugs.webkit.org/show_bug.cgi?id=184261
+
+ Reviewed by Carlos Garcia Campos.
+
+ On Linux we had two implementations for getting notifications about memory pressure events:
+ - The memory cgroup (called systemd here).
+ - The UIProcess memory monitor (which delivered events via a shared eventfd)
+
+ The problem with the first is that it was usually not working on a standard machine due to
+ the special permissions or configurations required for memory cgroups, so the second one
+ (eventfd) was used as a fall-back in that case.
+ But this eventfd method is racy with more than one WebKit child process and it wasn't
+ reliably delivering the notifications.
+
+ This patch removes the memory cgroup implementation and modifies the UIProcess memory monitor
+ to deliver the events via WebKit IPC. This simplifies the code a lot and allows us to have
+ only one implementation that should work in any Linux machine.
+
+ The implementation now also triggers the event with information about the criticalness of it.
+
+ Previously a critical event was triggered always at a 95% of pressure.
+ Now a non-critical one is triggered at 90% and critical remains at a 95%.
+
+ Start triggering events early should compensate the fact than triggering the event via WebKit IPC is
+ a bit slower than doing that via an eventfd (or than listening on the memory cgroup event controller).
+
+ The events are delivered to all WebKit childs: WebProcess, NetworkProcess, StorageProcess, PluginProcess.
+
+ In the case of the StorageProcess a dummy controller is installed, which currently does nothing,
+ but leaves a note for a future implementation and at least allows to trigger platformReleaseMemory()
+ that on Linux/glibc should end calling malloc_trim()
+
+ * NetworkProcess/NetworkProcess.cpp:
+ (WebKit::NetworkProcess::initializeNetworkProcess):
+ * NetworkProcess/NetworkProcessCreationParameters.cpp:
+ (WebKit::NetworkProcessCreationParameters::encode const):
+ (WebKit::NetworkProcessCreationParameters::decode):
+ * NetworkProcess/NetworkProcessCreationParameters.h:
+ * PluginProcess/PluginProcess.cpp:
+ (WebKit::PluginProcess::didReceiveMessage):
+ (WebKit::PluginProcess::initializePluginProcess):
+ * Shared/ChildProcess.cpp:
+ (WebKit::ChildProcess::didReceiveMemoryPressureEvent):
+ * Shared/ChildProcess.h:
+ * Shared/ChildProcess.messages.in:
+ * Shared/Plugins/PluginProcessCreationParameters.cpp:
+ (WebKit::PluginProcessCreationParameters::encode const):
+ (WebKit::PluginProcessCreationParameters::decode):
+ * Shared/Plugins/PluginProcessCreationParameters.h:
+ * Shared/WebProcessCreationParameters.cpp:
+ (WebKit::WebProcessCreationParameters::encode const):
+ (WebKit::WebProcessCreationParameters::decode):
+ * Shared/WebProcessCreationParameters.h:
+ * StorageProcess/StorageProcess.cpp:
+ (WebKit::StorageProcess::initializeProcess):
+ * UIProcess/Plugins/PluginProcessManager.cpp:
+ (WebKit::PluginProcessManager::sendMemoryPressureEvent):
+ * UIProcess/Plugins/PluginProcessManager.h:
+ * UIProcess/Plugins/PluginProcessProxy.cpp:
+ (WebKit::PluginProcessProxy::sendMemoryPressureEvent):
+ (WebKit::PluginProcessProxy::didFinishLaunching):
+ * UIProcess/Plugins/PluginProcessProxy.h:
+ * UIProcess/WebProcessPool.cpp:
+ (WebKit::WebProcessPool::sendMemoryPressureEvent):
+ (WebKit::WebProcessPool::ensureNetworkProcess):
+ (WebKit::WebProcessPool::initializeNewWebProcess):
+ * UIProcess/WebProcessPool.h:
+ (WebKit::WebProcessPool::sendToStorageProcess):
+ * UIProcess/linux/MemoryPressureMonitor.cpp:
+ (WebKit::pollIntervalForUsedMemoryPercentage): Fix equation for calculating the interval percentage.
+ (WebKit::MemoryPressureMonitor::singleton):
+ (WebKit::MemoryPressureMonitor::start):
+ * UIProcess/linux/MemoryPressureMonitor.h:
+ * WebProcess/WebProcess.cpp:
+ (WebKit::WebProcess::initializeWebProcess):
+
2018-05-24 Youenn Fablet <[email protected]>
Update plugin search path to look for user installed plugins
Modified: trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp (232175 => 232176)
--- trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp 2018-05-25 00:25:23 UTC (rev 232175)
+++ trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp 2018-05-25 00:52:13 UTC (rev 232176)
@@ -232,10 +232,6 @@
m_loadThrottleLatency = parameters.loadThrottleLatency;
if (!m_suppressMemoryPressureHandler) {
auto& memoryPressureHandler = MemoryPressureHandler::singleton();
-#if OS(LINUX)
- if (parameters.memoryPressureMonitorHandle.fileDescriptor() != -1)
- memoryPressureHandler.setMemoryPressureMonitorHandle(parameters.memoryPressureMonitorHandle.releaseFileDescriptor());
-#endif
memoryPressureHandler.setLowMemoryHandler([this] (Critical critical, Synchronous) {
lowMemoryHandler(critical);
});
Modified: trunk/Source/WebKit/NetworkProcess/NetworkProcessCreationParameters.cpp (232175 => 232176)
--- trunk/Source/WebKit/NetworkProcess/NetworkProcessCreationParameters.cpp 2018-05-25 00:25:23 UTC (rev 232175)
+++ trunk/Source/WebKit/NetworkProcess/NetworkProcessCreationParameters.cpp 2018-05-25 00:52:13 UTC (rev 232176)
@@ -100,9 +100,6 @@
#if HAVE(CFNETWORK_STORAGE_PARTITIONING) && !RELEASE_LOG_DISABLED
encoder << logCookieInformation;
#endif
-#if OS(LINUX)
- encoder << memoryPressureMonitorHandle;
-#endif
#if ENABLE(NETWORK_CAPTURE)
encoder << recordReplayMode;
encoder << recordReplayCacheLocation;
@@ -254,11 +251,6 @@
return false;
#endif
-#if OS(LINUX)
- if (!decoder.decode(result.memoryPressureMonitorHandle))
- return false;
-#endif
-
#if ENABLE(NETWORK_CAPTURE)
if (!decoder.decode(result.recordReplayMode))
return false;
Modified: trunk/Source/WebKit/NetworkProcess/NetworkProcessCreationParameters.h (232175 => 232176)
--- trunk/Source/WebKit/NetworkProcess/NetworkProcessCreationParameters.h 2018-05-25 00:25:23 UTC (rev 232175)
+++ trunk/Source/WebKit/NetworkProcess/NetworkProcessCreationParameters.h 2018-05-25 00:52:13 UTC (rev 232176)
@@ -25,7 +25,6 @@
#pragma once
-#include "Attachment.h"
#include "CacheModel.h"
#include "NetworkSessionCreationParameters.h"
#include "SandboxExtension.h"
@@ -116,10 +115,6 @@
bool logCookieInformation { false };
#endif
-#if OS(LINUX)
- IPC::Attachment memoryPressureMonitorHandle;
-#endif
-
#if ENABLE(NETWORK_CAPTURE)
String recordReplayMode;
String recordReplayCacheLocation;
Modified: trunk/Source/WebKit/PluginProcess/PluginProcess.cpp (232175 => 232176)
--- trunk/Source/WebKit/PluginProcess/PluginProcess.cpp 2018-05-25 00:25:23 UTC (rev 232175)
+++ trunk/Source/WebKit/PluginProcess/PluginProcess.cpp 2018-05-25 00:52:13 UTC (rev 232176)
@@ -30,6 +30,7 @@
#include "ArgumentCoders.h"
#include "Attachment.h"
+#include "ChildProcessMessages.h"
#include "NetscapePlugin.h"
#include "NetscapePluginModule.h"
#include "PluginProcessConnectionMessages.h"
@@ -116,6 +117,13 @@
void PluginProcess::didReceiveMessage(IPC::Connection& connection, IPC::Decoder& decoder)
{
+#if OS(LINUX)
+ if (decoder.messageReceiverName() == Messages::ChildProcess::messageReceiverName()) {
+ ChildProcess::didReceiveMessage(connection, decoder);
+ return;
+ }
+#endif
+
didReceivePluginProcessMessage(connection, decoder);
}
@@ -124,10 +132,6 @@
ASSERT(!m_pluginModule);
auto& memoryPressureHandler = MemoryPressureHandler::singleton();
-#if OS(LINUX)
- if (parameters.memoryPressureMonitorHandle.fileDescriptor() != -1)
- memoryPressureHandler.setMemoryPressureMonitorHandle(parameters.memoryPressureMonitorHandle.releaseFileDescriptor());
-#endif
memoryPressureHandler.setLowMemoryHandler([this] (Critical, Synchronous) {
if (shouldTerminate())
terminate();
Modified: trunk/Source/WebKit/Shared/ChildProcess.cpp (232175 => 232176)
--- trunk/Source/WebKit/Shared/ChildProcess.cpp 2018-05-25 00:25:23 UTC (rev 232175)
+++ trunk/Source/WebKit/Shared/ChildProcess.cpp 2018-05-25 00:52:13 UTC (rev 232176)
@@ -35,6 +35,10 @@
#include <unistd.h>
#endif
+#if OS(LINUX)
+#include <wtf/MemoryPressureHandler.h>
+#endif
+
using namespace WebCore;
namespace WebKit {
@@ -215,6 +219,14 @@
WTFLogAlways("Received invalid message: '%s::%s'", messageReceiverName.toString().data(), messageName.toString().data());
CRASH();
}
+
+#if OS(LINUX)
+void ChildProcess::didReceiveMemoryPressureEvent(bool isCritical)
+{
+ MemoryPressureHandler::singleton().triggerMemoryPressureEvent(isCritical);
+}
#endif
+#endif // !PLATFORM(COCOA)
+
} // namespace WebKit
Modified: trunk/Source/WebKit/Shared/ChildProcess.h (232175 => 232176)
--- trunk/Source/WebKit/Shared/ChildProcess.h 2018-05-25 00:25:23 UTC (rev 232175)
+++ trunk/Source/WebKit/Shared/ChildProcess.h 2018-05-25 00:52:13 UTC (rev 232176)
@@ -107,6 +107,9 @@
void didReceiveMessage(IPC::Connection&, IPC::Decoder&) override;
void registerURLSchemeServiceWorkersCanHandle(const String&) const;
+#if OS(LINUX)
+ void didReceiveMemoryPressureEvent(bool isCritical);
+#endif
private:
// IPC::MessageSender
Modified: trunk/Source/WebKit/Shared/ChildProcess.messages.in (232175 => 232176)
--- trunk/Source/WebKit/Shared/ChildProcess.messages.in 2018-05-25 00:25:23 UTC (rev 232175)
+++ trunk/Source/WebKit/Shared/ChildProcess.messages.in 2018-05-25 00:52:13 UTC (rev 232176)
@@ -24,4 +24,8 @@
ShutDown()
RegisterURLSchemeServiceWorkersCanHandle(String scheme)
SetProcessSuppressionEnabled(bool flag)
+
+#if OS(LINUX)
+ void DidReceiveMemoryPressureEvent(bool isCritical)
+#endif
}
Modified: trunk/Source/WebKit/Shared/Plugins/PluginProcessCreationParameters.cpp (232175 => 232176)
--- trunk/Source/WebKit/Shared/Plugins/PluginProcessCreationParameters.cpp 2018-05-25 00:25:23 UTC (rev 232175)
+++ trunk/Source/WebKit/Shared/Plugins/PluginProcessCreationParameters.cpp 2018-05-25 00:52:13 UTC (rev 232176)
@@ -49,9 +49,6 @@
encoder << acceleratedCompositingPort;
IPC::encode(encoder, networkATSContext.get());
#endif
-#if OS(LINUX)
- encoder << memoryPressureMonitorHandle;
-#endif
}
bool PluginProcessCreationParameters::decode(IPC::Decoder& decoder, PluginProcessCreationParameters& result)
@@ -70,10 +67,6 @@
if (!IPC::decode(decoder, result.networkATSContext))
return false;
#endif
-#if OS(LINUX)
- if (!decoder.decode(result.memoryPressureMonitorHandle))
- return false;
-#endif
return true;
}
Modified: trunk/Source/WebKit/Shared/Plugins/PluginProcessCreationParameters.h (232175 => 232176)
--- trunk/Source/WebKit/Shared/Plugins/PluginProcessCreationParameters.h 2018-05-25 00:25:23 UTC (rev 232175)
+++ trunk/Source/WebKit/Shared/Plugins/PluginProcessCreationParameters.h 2018-05-25 00:52:13 UTC (rev 232176)
@@ -27,7 +27,6 @@
#if ENABLE(NETSCAPE_PLUGIN_API)
-#include "Attachment.h"
#include "PluginProcessAttributes.h"
#include <wtf/Seconds.h>
@@ -58,9 +57,6 @@
WTF::MachSendRight acceleratedCompositingPort;
RetainPtr<CFDataRef> networkATSContext;
#endif
-#if OS(LINUX)
- IPC::Attachment memoryPressureMonitorHandle;
-#endif
};
} // namespace WebKit
Modified: trunk/Source/WebKit/Shared/WebProcessCreationParameters.cpp (232175 => 232176)
--- trunk/Source/WebKit/Shared/WebProcessCreationParameters.cpp 2018-05-25 00:25:23 UTC (rev 232175)
+++ trunk/Source/WebKit/Shared/WebProcessCreationParameters.cpp 2018-05-25 00:52:13 UTC (rev 232176)
@@ -139,10 +139,6 @@
IPC::encode(encoder, networkATSContext.get());
#endif
-#if OS(LINUX)
- encoder << memoryPressureMonitorHandle;
-#endif
-
#if PLATFORM(WAYLAND)
encoder << waylandCompositorDisplayName;
#endif
@@ -385,11 +381,6 @@
return false;
#endif
-#if OS(LINUX)
- if (!decoder.decode(parameters.memoryPressureMonitorHandle))
- return false;
-#endif
-
#if PLATFORM(WAYLAND)
if (!decoder.decode(parameters.waylandCompositorDisplayName))
return false;
Modified: trunk/Source/WebKit/Shared/WebProcessCreationParameters.h (232175 => 232176)
--- trunk/Source/WebKit/Shared/WebProcessCreationParameters.h 2018-05-25 00:25:23 UTC (rev 232175)
+++ trunk/Source/WebKit/Shared/WebProcessCreationParameters.h 2018-05-25 00:52:13 UTC (rev 232176)
@@ -173,10 +173,6 @@
RetainPtr<CFDataRef> networkATSContext;
#endif
-#if OS(LINUX)
- IPC::Attachment memoryPressureMonitorHandle;
-#endif
-
#if PLATFORM(WAYLAND)
String waylandCompositorDisplayName;
#endif
Modified: trunk/Source/WebKit/StorageProcess/StorageProcess.cpp (232175 => 232176)
--- trunk/Source/WebKit/StorageProcess/StorageProcess.cpp 2018-05-25 00:25:23 UTC (rev 232175)
+++ trunk/Source/WebKit/StorageProcess/StorageProcess.cpp 2018-05-25 00:52:13 UTC (rev 232176)
@@ -49,7 +49,9 @@
#include <wtf/CallbackAggregator.h>
#include <wtf/CrossThreadTask.h>
#include <wtf/MainThread.h>
+#include <wtf/MemoryPressureHandler.h>
+
#if ENABLE(SERVICE_WORKER)
#include "WebSWServerToContextConnectionMessages.h"
#endif
@@ -555,6 +557,14 @@
#if !PLATFORM(COCOA)
void StorageProcess::initializeProcess(const ChildProcessInitializationParameters&)
{
+#if OS(LINUX)
+ auto& memoryPressureHandler = MemoryPressureHandler::singleton();
+ memoryPressureHandler.setLowMemoryHandler([this] (Critical, Synchronous) {
+ // FIXME: no lowMemoryHandler() implemented for StorageProcess currently.
+ // But at least define this setLowMemoryHandler() empty so platformReleaseMemory is called.
+ });
+ memoryPressureHandler.install();
+#endif
}
void StorageProcess::initializeProcessName(const ChildProcessInitializationParameters&)
@@ -564,6 +574,6 @@
void StorageProcess::initializeSandbox(const ChildProcessInitializationParameters&, SandboxInitializationParameters&)
{
}
-#endif
+#endif // !PLATFORM(COCOA)
} // namespace WebKit
Modified: trunk/Source/WebKit/UIProcess/Plugins/PluginProcessManager.cpp (232175 => 232176)
--- trunk/Source/WebKit/UIProcess/Plugins/PluginProcessManager.cpp 2018-05-25 00:25:23 UTC (rev 232175)
+++ trunk/Source/WebKit/UIProcess/Plugins/PluginProcessManager.cpp 2018-05-25 00:52:13 UTC (rev 232176)
@@ -131,6 +131,14 @@
return nullptr;
}
+#if OS(LINUX)
+void PluginProcessManager::sendMemoryPressureEvent(bool isCritical)
+{
+ for (auto& pluginProcess : m_pluginProcesses)
+ pluginProcess->sendMemoryPressureEvent(isCritical);
+}
+#endif
+
PluginProcessProxy* PluginProcessManager::getOrCreatePluginProcess(uint64_t pluginProcessToken)
{
if (auto existingProcess = getPluginProcess(pluginProcessToken))
Modified: trunk/Source/WebKit/UIProcess/Plugins/PluginProcessManager.h (232175 => 232176)
--- trunk/Source/WebKit/UIProcess/Plugins/PluginProcessManager.h 2018-05-25 00:25:23 UTC (rev 232175)
+++ trunk/Source/WebKit/UIProcess/Plugins/PluginProcessManager.h 2018-05-25 00:52:13 UTC (rev 232176)
@@ -64,6 +64,10 @@
void deleteWebsiteData(const PluginModuleInfo&, WallTime modifiedSince, WTF::Function<void ()>&& completionHandler);
void deleteWebsiteDataForHostNames(const PluginModuleInfo&, const Vector<String>& hostNames, WTF::Function<void ()>&& completionHandler);
+#if OS(LINUX)
+ void sendMemoryPressureEvent(bool isCritical);
+#endif
+
#if PLATFORM(COCOA)
inline ProcessSuppressionDisabledToken processSuppressionDisabledToken();
inline bool processSuppressionDisabled() const;
Modified: trunk/Source/WebKit/UIProcess/Plugins/PluginProcessProxy.cpp (232175 => 232176)
--- trunk/Source/WebKit/UIProcess/Plugins/PluginProcessProxy.cpp 2018-05-25 00:25:23 UTC (rev 232175)
+++ trunk/Source/WebKit/UIProcess/Plugins/PluginProcessProxy.cpp 2018-05-25 00:52:13 UTC (rev 232176)
@@ -28,6 +28,7 @@
#if ENABLE(NETSCAPE_PLUGIN_API)
+#include "ChildProcessMessages.h"
#include "PluginProcessConnectionManagerMessages.h"
#include "PluginProcessCreationParameters.h"
#include "PluginProcessManager.h"
@@ -38,10 +39,6 @@
#include <WebCore/NotImplemented.h>
#include <wtf/RunLoop.h>
-#if OS(LINUX)
-#include "MemoryPressureMonitor.h"
-#endif
-
using namespace WebCore;
namespace WebKit {
@@ -155,6 +152,16 @@
m_connection->send(Messages::PluginProcess::DeleteWebsiteDataForHostNames(hostNames, callbackID), 0);
}
+#if OS(LINUX)
+void PluginProcessProxy::sendMemoryPressureEvent(bool isCritical)
+{
+ if (state() == State::Launching)
+ return;
+
+ m_connection->send(Messages::ChildProcess::DidReceiveMemoryPressureEvent(isCritical), 0);
+}
+#endif
+
void PluginProcessProxy::pluginProcessCrashedOrFailedToLaunch()
{
// The plug-in process must have crashed or exited, send any pending sync replies we might have.
@@ -234,11 +241,6 @@
parameters.terminationTimeout = shutdownTimeout;
}
-#if OS(LINUX)
- if (MemoryPressureMonitor::isEnabled())
- parameters.memoryPressureMonitorHandle = MemoryPressureMonitor::singleton().createHandle();
-#endif
-
platformInitializePluginProcess(parameters);
// Initialize the plug-in host process.
Modified: trunk/Source/WebKit/UIProcess/Plugins/PluginProcessProxy.h (232175 => 232176)
--- trunk/Source/WebKit/UIProcess/Plugins/PluginProcessProxy.h 2018-05-25 00:25:23 UTC (rev 232175)
+++ trunk/Source/WebKit/UIProcess/Plugins/PluginProcessProxy.h 2018-05-25 00:52:13 UTC (rev 232176)
@@ -82,6 +82,10 @@
void deleteWebsiteData(WallTime modifiedSince, WTF::Function<void ()>&& completionHandler);
void deleteWebsiteDataForHostNames(const Vector<String>& hostNames, WTF::Function<void ()>&& completionHandler);
+#if OS(LINUX)
+ void sendMemoryPressureEvent(bool isCritical);
+#endif
+
bool isValid() const { return m_connection; }
#if PLUGIN_ARCHITECTURE(UNIX)
Modified: trunk/Source/WebKit/UIProcess/WebProcessPool.cpp (232175 => 232176)
--- trunk/Source/WebKit/UIProcess/WebProcessPool.cpp 2018-05-25 00:25:23 UTC (rev 232175)
+++ trunk/Source/WebKit/UIProcess/WebProcessPool.cpp 2018-05-25 00:52:13 UTC (rev 232176)
@@ -49,6 +49,7 @@
#include "NetworkProcessMessages.h"
#include "NetworkProcessProxy.h"
#include "PerActivityStateCPUUsageSampler.h"
+#include "PluginProcessManager.h"
#include "SandboxExtension.h"
#include "ServiceWorkerProcessProxy.h"
#include "StatisticsData.h"
@@ -269,6 +270,10 @@
platformInitialize();
+#if OS(LINUX)
+ MemoryPressureMonitor::singleton().start();
+#endif
+
addMessageReceiver(Messages::WebProcessPool::messageReceiverName(), *this);
// NOTE: These sub-objects must be initialized after m_messageReceiverMap..
@@ -413,6 +418,18 @@
sendToAllProcesses(Messages::WebProcess::FullKeyboardAccessModeChanged(fullKeyboardAccessEnabled));
}
+#if OS(LINUX)
+void WebProcessPool::sendMemoryPressureEvent(bool isCritical)
+{
+ sendToAllProcesses(Messages::ChildProcess::DidReceiveMemoryPressureEvent(isCritical));
+ sendToNetworkingProcess(Messages::ChildProcess::DidReceiveMemoryPressureEvent(isCritical));
+ sendToStorageProcess(Messages::ChildProcess::DidReceiveMemoryPressureEvent(isCritical));
+#if ENABLE(NETSCAPE_PLUGIN_API)
+ PluginProcessManager::singleton().sendMemoryPressureEvent(isCritical);
+#endif
+}
+#endif
+
void WebProcessPool::textCheckerStateChanged()
{
sendToAllProcesses(Messages::WebProcess::SetTextCheckerState(TextChecker::state()));
@@ -490,11 +507,6 @@
SandboxExtension::createHandle(parentBundleDirectory, SandboxExtension::Type::ReadOnly, parameters.parentBundleDirectoryExtensionHandle);
#endif
-#if OS(LINUX)
- if (MemoryPressureMonitor::isEnabled())
- parameters.memoryPressureMonitorHandle = MemoryPressureMonitor::singleton().createHandle();
-#endif
-
parameters.shouldUseTestingNetworkSession = m_shouldUseTestingNetworkSession;
parameters.presentingApplicationPID = m_configuration->presentingApplicationPID();
@@ -923,8 +935,6 @@
#if OS(LINUX)
parameters.shouldEnableMemoryPressureReliefLogging = true;
- if (MemoryPressureMonitor::isEnabled())
- parameters.memoryPressureMonitorHandle = MemoryPressureMonitor::singleton().createHandle();
#endif
#if PLATFORM(WAYLAND) && USE(EGL)
Modified: trunk/Source/WebKit/UIProcess/WebProcessPool.h (232175 => 232176)
--- trunk/Source/WebKit/UIProcess/WebProcessPool.h 2018-05-25 00:25:23 UTC (rev 232175)
+++ trunk/Source/WebKit/UIProcess/WebProcessPool.h 2018-05-25 00:52:13 UTC (rev 232176)
@@ -165,6 +165,7 @@
template<typename T> void sendToNetworkingProcessRelaunchingIfNecessary(T&& message);
// Sends the message to WebProcess or StorageProcess as approporiate for current process model.
+ template<typename T> void sendToStorageProcess(T&& message);
template<typename T> void sendToStorageProcessRelaunchingIfNecessary(T&& message);
void processDidFinishLaunching(WebProcessProxy*);
@@ -313,7 +314,9 @@
#endif
void fullKeyboardAccessModeChanged(bool fullKeyboardAccessEnabled);
-
+#if OS(LINUX)
+ void sendMemoryPressureEvent(bool isCritical);
+#endif
void textCheckerStateChanged();
Ref<API::Dictionary> plugInAutoStartOriginHashes() const;
@@ -714,6 +717,13 @@
}
template<typename T>
+void WebProcessPool::sendToStorageProcess(T&& message)
+{
+ if (m_storageProcess && m_storageProcess->canSendMessage())
+ m_storageProcess->send(std::forward<T>(message), 0);
+}
+
+template<typename T>
void WebProcessPool::sendToStorageProcessRelaunchingIfNecessary(T&& message)
{
ensureStorageProcessAndWebsiteDataStore(nullptr);
Modified: trunk/Source/WebKit/UIProcess/linux/MemoryPressureMonitor.cpp (232175 => 232176)
--- trunk/Source/WebKit/UIProcess/linux/MemoryPressureMonitor.cpp 2018-05-25 00:25:23 UTC (rev 232175)
+++ trunk/Source/WebKit/UIProcess/linux/MemoryPressureMonitor.cpp 2018-05-25 00:52:13 UTC (rev 232176)
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2016 Igalia S.L.
+ * Copyright (C) 2016, 2018 Igalia S.L.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -28,15 +28,10 @@
#if OS(LINUX)
-#include "Attachment.h"
-#include <errno.h>
-#include <fcntl.h>
-#include <mutex>
+#include "WebProcessPool.h"
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <sys/eventfd.h>
-#include <sys/stat.h>
-#include <sys/types.h>
#include <unistd.h>
#include <wtf/Threading.h>
#include <wtf/UniStdExtras.h>
@@ -48,8 +43,9 @@
static const Seconds s_minPollingInterval { 1_s };
static const Seconds s_maxPollingInterval { 5_s };
static const double s_minUsedMemoryPercentageForPolling = 50;
-static const double s_maxUsedMemoryPercentageForPolling = 90;
-static const int s_memoryPresurePercentageThreshold = 95;
+static const double s_maxUsedMemoryPercentageForPolling = 85;
+static const int s_memoryPresurePercentageThreshold = 90;
+static const int s_memoryPresurePercentageThresholdCritical = 95;
static size_t lowWatermarkPages()
{
@@ -208,45 +204,22 @@
return s_minPollingInterval;
return s_minPollingInterval + (s_maxPollingInterval - s_minPollingInterval) *
- ((usedPercentage - s_minUsedMemoryPercentageForPolling) / (s_maxUsedMemoryPercentageForPolling - s_minUsedMemoryPercentageForPolling));
+ ((s_maxUsedMemoryPercentageForPolling - usedPercentage) / (s_maxUsedMemoryPercentageForPolling - s_minUsedMemoryPercentageForPolling));
}
-static bool isSystemdMemoryPressureMonitorAvailable()
-{
- int fd = open("/sys/fs/cgroup/memory/memory.pressure_level", O_CLOEXEC | O_RDONLY);
- if (fd == -1)
- return false;
- close(fd);
-
- fd = open("/sys/fs/cgroup/memory/cgroup.event_control", O_CLOEXEC | O_WRONLY);
- if (fd == -1)
- return false;
- close(fd);
-
- return true;
-}
-
-bool MemoryPressureMonitor::isEnabled()
-{
- static std::once_flag onceFlag;
- static bool enabled;
- std::call_once(onceFlag, [] { enabled = !isSystemdMemoryPressureMonitorAvailable(); });
- return enabled;
-}
-
MemoryPressureMonitor& MemoryPressureMonitor::singleton()
{
- ASSERT(isEnabled());
static NeverDestroyed<MemoryPressureMonitor> memoryMonitor;
return memoryMonitor;
}
-MemoryPressureMonitor::MemoryPressureMonitor()
- : m_eventFD(eventfd(0, EFD_CLOEXEC))
+void MemoryPressureMonitor::start()
{
- if (m_eventFD == -1)
+ if (m_started)
return;
+ m_started = true;
+
Thread::create("MemoryPressureMonitor", [this] {
Seconds pollInterval = s_maxPollingInterval;
while (true) {
@@ -259,26 +232,15 @@
}
if (usedPercentage >= s_memoryPresurePercentageThreshold) {
- uint64_t fdEvent = 1;
- ssize_t bytesWritten = write(m_eventFD, &fdEvent, sizeof(uint64_t));
- if (bytesWritten != sizeof(uint64_t)) {
- WTFLogAlways("Error writing to MemoryPressureMonitor eventFD: %s", strerror(errno));
- break;
- }
+ bool isCritical = (usedPercentage >= s_memoryPresurePercentageThresholdCritical);
+ for (auto* processPool : WebProcessPool::allProcessPools())
+ processPool->sendMemoryPressureEvent(isCritical);
}
pollInterval = pollIntervalForUsedMemoryPercentage(usedPercentage);
}
- close(m_eventFD);
})->detach();
}
-IPC::Attachment MemoryPressureMonitor::createHandle() const
-{
- int duplicatedHandle = dupCloseOnExec(m_eventFD);
- if (duplicatedHandle == -1)
- return { };
- return IPC::Attachment(duplicatedHandle);
-}
} // namespace WebKit
Modified: trunk/Source/WebKit/UIProcess/linux/MemoryPressureMonitor.h (232175 => 232176)
--- trunk/Source/WebKit/UIProcess/linux/MemoryPressureMonitor.h 2018-05-25 00:25:23 UTC (rev 232175)
+++ trunk/Source/WebKit/UIProcess/linux/MemoryPressureMonitor.h 2018-05-25 00:52:13 UTC (rev 232176)
@@ -41,16 +41,13 @@
friend NeverDestroyed<MemoryPressureMonitor>;
public:
static MemoryPressureMonitor& singleton();
- static bool isEnabled();
+ void start();
~MemoryPressureMonitor();
- IPC::Attachment createHandle() const;
-
private:
- MemoryPressureMonitor();
-
- int m_eventFD { -1 };
+ MemoryPressureMonitor() = default;
+ bool m_started { false };
};
} // namespace WebKit
Modified: trunk/Source/WebKit/WebProcess/WebProcess.cpp (232175 => 232176)
--- trunk/Source/WebKit/WebProcess/WebProcess.cpp 2018-05-25 00:25:23 UTC (rev 232175)
+++ trunk/Source/WebKit/WebProcess/WebProcess.cpp 2018-05-25 00:52:13 UTC (rev 232176)
@@ -270,8 +270,6 @@
WebCore::setPresentingApplicationPID(parameters.presentingApplicationPID);
#if OS(LINUX)
- if (parameters.memoryPressureMonitorHandle.fileDescriptor() != -1)
- MemoryPressureHandler::singleton().setMemoryPressureMonitorHandle(parameters.memoryPressureMonitorHandle.releaseFileDescriptor());
MemoryPressureHandler::ReliefLogger::setLoggingEnabled(parameters.shouldEnableMemoryPressureReliefLogging);
#endif