Reviewed by Sam Weinig.
<rdar://problem/
6562220>
CrashTracer: [USER] 21 crashes in Safari at com.apple.WebKit • WebKit::NetscapePluginHostProxy::port
Make the handling of crashes in the plug-in host more robust.
* Plugins/Hosted/NetscapePluginHostProxy.h:
Add m_portSet.
* Plugins/Hosted/NetscapePluginHostProxy.mm:
(WebKit::NetscapePluginHostProxy::NetscapePluginHostProxy):
Initialize m_portSet.
(WebKit::NetscapePluginHostProxy::~NetscapePluginHostProxy):
Free m_portSet.
(WebKit::NetscapePluginHostProxy::processRequests):
Listen for messages on the port set. If we get a message to the port death notification port,
then call pluginHostDied. Otherwise, process the message.
* Plugins/Hosted/NetscapePluginInstanceProxy.h:
* Plugins/Hosted/NetscapePluginInstanceProxy.mm:
(WebKit::NetscapePluginInstanceProxy::cleanup):
Factor code that should be shared between destroy() and pluginHostDied() into cleanup.
(WebKit::NetscapePluginInstanceProxy::destroy):
Call cleanup().
(WebKit::NetscapePluginInstanceProxy::pluginHostDied):
Call cleanup().
(WebKit::NetscapePluginInstanceProxy::processRequestsAndWaitForReply):
Call NetscapePluginHostProxy::processRequests.
* Plugins/Hosted/ProxyInstance.mm:
(WebKit::ProxyInstance::invalidate):
Add a null check for the host proxy.
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@40733
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2009-02-06 Anders Carlsson <andersca@apple.com>
+
+ Reviewed by Sam Weinig.
+
+ <rdar://problem/6562220>
+ CrashTracer: [USER] 21 crashes in Safari at com.apple.WebKit • WebKit::NetscapePluginHostProxy::port
+
+ Make the handling of crashes in the plug-in host more robust.
+
+ * Plugins/Hosted/NetscapePluginHostProxy.h:
+ Add m_portSet.
+
+ * Plugins/Hosted/NetscapePluginHostProxy.mm:
+ (WebKit::NetscapePluginHostProxy::NetscapePluginHostProxy):
+ Initialize m_portSet.
+
+ (WebKit::NetscapePluginHostProxy::~NetscapePluginHostProxy):
+ Free m_portSet.
+
+ (WebKit::NetscapePluginHostProxy::processRequests):
+ Listen for messages on the port set. If we get a message to the port death notification port,
+ then call pluginHostDied. Otherwise, process the message.
+
+ * Plugins/Hosted/NetscapePluginInstanceProxy.h:
+ * Plugins/Hosted/NetscapePluginInstanceProxy.mm:
+ (WebKit::NetscapePluginInstanceProxy::cleanup):
+ Factor code that should be shared between destroy() and pluginHostDied() into cleanup.
+
+ (WebKit::NetscapePluginInstanceProxy::destroy):
+ Call cleanup().
+
+ (WebKit::NetscapePluginInstanceProxy::pluginHostDied):
+ Call cleanup().
+
+ (WebKit::NetscapePluginInstanceProxy::processRequestsAndWaitForReply):
+ Call NetscapePluginHostProxy::processRequests.
+
+ * Plugins/Hosted/ProxyInstance.mm:
+ (WebKit::ProxyInstance::invalidate):
+ Add a null check for the host proxy.
+
2009-02-06 Dan Bernstein <mitz@apple.com>
- try to fix the Tiger build
void applicationDidBecomeActive();
+ bool processRequests();
+
private:
~NetscapePluginHostProxy();
void pluginHostDied();
PluginInstanceMap m_instances;
mach_port_t m_clientPort;
+ mach_port_t m_portSet;
+
#ifdef USE_LIBDISPATCH
dispatch_source_t m_clientPortSource;
#else
NetscapePluginHostProxy::NetscapePluginHostProxy(mach_port_t clientPort, mach_port_t pluginHostPort, const ProcessSerialNumber& pluginHostPSN)
: m_clientPort(clientPort)
+ , m_portSet(MACH_PORT_NULL)
, m_pluginHostPort(pluginHostPort)
, m_isModal(false)
, m_menuBarIsVisible(true)
NetscapePluginHostProxy::~NetscapePluginHostProxy()
{
pluginProxyMap().remove(m_clientPort);
+
+ // Free the port set
+ if (m_portSet) {
+ mach_port_extract_member(mach_task_self(), m_clientPort, m_portSet);
+ mach_port_extract_member(mach_task_self(), CFMachPortGetPort(m_deadNameNotificationPort.get()), m_portSet);
+ mach_port_destroy(mach_task_self(), m_portSet);
+ }
ASSERT(m_clientPortSource);
#ifdef USE_LIBDISPATCH
endModal();
}
+bool NetscapePluginHostProxy::processRequests()
+{
+ if (!m_portSet) {
+ mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_PORT_SET, &m_portSet);
+ mach_port_insert_member(mach_task_self(), m_clientPort, m_portSet);
+ mach_port_insert_member(mach_task_self(), CFMachPortGetPort(m_deadNameNotificationPort.get()), m_portSet);
+ }
+
+ char buffer[4096];
+
+ mach_msg_header_t* msg = reinterpret_cast<mach_msg_header_t*>(buffer);
+
+ kern_return_t kr = mach_msg(msg, MACH_RCV_MSG, 0, sizeof(buffer), m_portSet, 0, MACH_PORT_NULL);
+
+ if (kr != KERN_SUCCESS) {
+ LOG_ERROR("Could not receive mach message, error %x", kr);
+ return false;
+ }
+
+ if (msg->msgh_local_port == m_clientPort) {
+ __ReplyUnion__WKWebKitPluginClient_subsystem reply;
+ mach_msg_header_t* replyHeader = reinterpret_cast<mach_msg_header_t*>(&reply);
+
+ if (WebKitPluginClient_server(msg, replyHeader) && replyHeader->msgh_remote_port != MACH_PORT_NULL) {
+ kr = mach_msg(replyHeader, MACH_SEND_MSG, replyHeader->msgh_size, 0, MACH_PORT_NULL, 0, MACH_PORT_NULL);
+
+ if (kr != KERN_SUCCESS) {
+ LOG_ERROR("Could not send mach message, error %x", kr);
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ if (msg->msgh_local_port == CFMachPortGetPort(m_deadNameNotificationPort.get())) {
+ ASSERT(msg->msgh_id == MACH_NOTIFY_DEAD_NAME);
+ pluginHostDied();
+ return false;
+ }
+
+ ASSERT_NOT_REACHED();
+ return false;
+}
+
} // namespace WebKit
using namespace WebKit;
void stopAllStreams();
void processRequestsAndWaitForReply();
+ void cleanup();
+
NetscapePluginHostProxy* m_pluginHostProxy;
WebHostedNetscapePluginView *m_pluginView;
streamsCopy[i]->stop();
}
-void NetscapePluginInstanceProxy::destroy()
+void NetscapePluginInstanceProxy::cleanup()
{
stopAllStreams();
- _WKPHDestroyPluginInstance(m_pluginHostProxy->port(), m_pluginID);
-
// Clear the object map, this will cause any outstanding JS objects that the plug-in had a reference to
// to go away when the next garbage collection takes place.
m_objects.clear();
-
+
if (Frame* frame = core([m_pluginView webFrame]))
frame->script()->cleanupScriptObjectsForPlugin(m_pluginView);
ProxyInstanceSet::const_iterator end = instances.end();
for (ProxyInstanceSet::const_iterator it = instances.begin(); it != end; ++it)
(*it)->invalidate();
-
+}
+
+void NetscapePluginInstanceProxy::destroy()
+{
+ _WKPHDestroyPluginInstance(m_pluginHostProxy->port(), m_pluginID);
+
+ cleanup();
+
m_pluginHostProxy->removePluginInstance(this);
m_pluginHostProxy = 0;
}
void NetscapePluginInstanceProxy::pluginHostDied()
{
- stopAllStreams();
-
m_pluginHostProxy = 0;
+
+ cleanup();
[m_pluginView pluginHostDied];
m_pluginView = nil;
void NetscapePluginInstanceProxy::processRequestsAndWaitForReply()
{
while (!m_currentReply.get()) {
- kern_return_t kr = mach_msg_server_once(WebKitPluginClient_server, WKWebKitPluginClient_subsystem.maxsize + MAX_TRAILER_SIZE, m_pluginHostProxy->clientPort(), 0);
- if (kr != KERN_SUCCESS) {
+ if (!m_pluginHostProxy->processRequests()) {
m_currentReply.reset();
break;
}
void ProxyInstance::invalidate()
{
- _WKPHNPObjectRelease(m_instanceProxy->hostProxy()->port(),
- m_instanceProxy->pluginID(), m_objectID);
+ if (NetscapePluginHostProxy* hostProxy = m_instanceProxy->hostProxy())
+ _WKPHNPObjectRelease(hostProxy->port(),
+ m_instanceProxy->pluginID(), m_objectID);
m_instanceProxy = 0;
}