Updates:
Cc: [email protected] [email protected]
Comment #13 on issue 27510 by [email protected]: Chrome crashes during
reload a page with Flash Player crashed object
http://code.google.com/p/chromium/issues/detail?id=27510
I was investigating bug 26754 and took a detour over to this bug because it
seems
like a similar IPC problem, and because I can reproduce this one.
Being able to reproduce it means that I can diagnose it and learn fun
things about
our IPC system at the same time!
This bug is caused by a thread race conflicting with the lifetime of the
transport DIB.
The problem we're seeing is EBADF from sendmsg while the renderer process is
trying to send to the plugin process. The bad file descriptor isn't the
pipe's
descriptor, it's the descriptor that the renderer is trying to send. EBADF
occurs with
this stack on the IPC thread:
#0 IPC::Channel::ChannelImpl::ProcessOutgoingMessages (this=0x89d000) at
/chrome/trunk/src/ipc/ipc_channel_posix.cc:828
#1 0x0767eea3 in IPC::Channel::ChannelImpl::Send (this=0x89d000,
message=0x21b0eed0) at /chrome/trunk/src/ipc/ipc_channel_posix.cc:879
#2 0x0767eedf in IPC::Channel::Send (this=0x1b6930, message=0x21b0eed0) at
/chrome/trunk/src/ipc/ipc_channel_posix.cc:1024
#3 0x07682015 in IPC::ChannelProxy::Context::OnSendMessage (this=0x1b6e50,
message=0x21b0eed0) at /chrome/trunk/src/ipc/ipc_channel_proxy.cc:156
#4 0x07683857 in IPC::SendTask::Run (this=0x12ae30) at
/chrome/trunk/src/ipc/ipc_channel_proxy.cc:25
(trimmed)
Here's where the offending SendTask is born, on the renderer thread, where
it is
posted to the IPC thread's message loop:
#0 IPC::ChannelProxy::Send (this=0x1ba470, message=0x21a24730) at
/chrome/trunk/src/ipc/ipc_channel_proxy.cc:276
#1 0x0768b82a in IPC::SyncChannel::SendWithTimeout (this=0x1ba470,
message=0x21a24730, timeout_ms=-1) at
/chrome/trunk/src/ipc/ipc_sync_channel.cc:381
#2 0x0768a835 in IPC::SyncChannel::Send (this=0x1ba470, message=0x21a24730)
at /chrome/trunk/src/ipc/ipc_sync_channel.cc:376
#3 0x082fbe5e in PluginChannelBase::Send (this=0x1ba700,
message=0x21a24730) at
/chrome/trunk/src/chrome/plugin/plugin_channel_base.cc:117
#4 0x06f8f38c in WebPluginDelegateProxy::Send (this=0x21a1e600,
msg=0x21a24730) at
/chrome/trunk/src/chrome/renderer/webplugin_delegate_proxy.cc:304
#5 0x06f91ea9 in WebPluginDelegateProxy::UpdateGeometry (this=0x21a1e600,
window_re...@0x21a1c1a4, clip_re...@0x21a1c1b4) at
/chrome/trunk/src/chrome/renderer/webplugin_delegate_proxy.cc:463
#6 0x081ffea5 in webkit_glue::WebPluginImpl::updateGeometry
(this=0x21a1c110,
window_re...@0xbfffc7b0, clip_re...@0xbfffc7a0, cutout_rec...@0xbfffc798,
is_visible=true) at /chrome/trunk/src/webkit/glue/webplugin_impl.cc:272
#7 0x0783f32a in WebKit::WebPluginContainerImpl::reportGeometry
(this=0x21a1e090) at
/chrome/trunk/src/third_party/WebKit/WebKit/chromium/src/WebPluginContainerI
mpl.cpp:221
(trimmed)
Frame 5, WebPluginDelegateProxy::UpdateGeometry, is crucial. The "bad" file
descriptor is placed into the message as param.windowless_buffer.fd, which
comes
from the WebPluginDelegateProxy's transport_store_->handle().fd. The
transport
store (TransportDIB)'s file descriptor is good at the point that it's
inserted into the
message.
Earlier in WebPluginDelegateProxy::UpdateGeometry, windowless_buffer_ may be
destroyed (and replaced). That happens on this renderer thread stack:
#0 base::SharedMemory::Close (this=0x21a39660) at
/chrome/trunk/src/base/shared_memory_posix.cc:287
#1 0x07017d4b in base::SharedMemory::~SharedMemory (this=0x21a39660) at
/chrome/trunk/src/base/shared_memory_posix.cc:64
#2 0x069770d1 in TransportDIB::~TransportDIB (this=0x21a39660) at
/chrome/trunk/src/chrome/common/transport_dib_mac.cc:24
#3 0x0830d143 in scoped_ptr<TransportDIB>::reset (this=0x21a25208, p=0x0)
at
scoped_ptr.h:81
#4 0x06f91844 in WebPluginDelegateProxy::ResetWindowlessBitmaps
(this=0x21a25190) at
/chrome/trunk/src/chrome/renderer/webplugin_delegate_proxy.cc:484
#5 0x06f91a15 in WebPluginDelegateProxy::UpdateGeometry (this=0x21a25190,
window_re...@0x21a14824, clip_re...@0x21a14834) at
/chrome/trunk/src/chrome/renderer/webplugin_delegate_proxy.cc:413
(trimmed)
When the base::SharedMemory is closed (for replacement or otherwise), its
associated
file descriptor is closed.
This results in a race: if we enter WebPluginDelegateProxy::UpdateGeometry a
subsequent time while the IPC::SendTask from an earlier call is still
pending, it's
possible to close the file descriptor that the pending task is still
carrying.
In most cases, WebPluginDelegateProxy::UpdateGeometry will simply replace
the
base::SharedMemory object with a new one that will wind up with the same
file
descriptor as the old one. However, it's possible for a different file
descriptor to be
assigned. It's also possible that the IPC thread will run the
IPC::SendTask and wind
up in IPC::Channel::ChannelImpl::ProcessOutgoingMessages after the renderer
thread's WebPluginDelegateProxy::UpdateGeometry has closed the old file
descriptor
but before it's opened the new one.
Kaboom. There's your race. The IPC channel goes dead, even though the
plugin
process doesn't crash. You get a sad plug-in.
Now reload the page. Because of some sick twist,
IPC::Channel::ChannelImpl::ProcessOutgoingMessages
(ipc/ipc_channel_posix.cc)
doesn't close down the channel when an unexpected send error occurs, like
EBADF.
Hit reload and the renderer process will attempt to reestablish IPC with
the plugin
process using the same channel name. It'll find the existing IPC pipe file
descriptor
in its map (because it was never closed) and try to recycle it. Treating
the kinda-
sorta half-open channel as a brand new pipe in some ways, we'll go through
the
"hello" message handshake thing and fire off all of the usual
OnChannelConnected
callbacks, which starts upsetting parts of the program that are aware
(either directly
or as a side effect) that the channel once was connected and really
shouldn't be
going through that bring-up all over again.
Kaboom. There's your crash.
--
You received this message because you are listed in the owner
or CC fields of this issue, or because you starred this issue.
You may adjust your issue notification preferences at:
http://code.google.com/hosting/settings
--
Automated mail from issue updates at http://crbug.com/
Subscription options: http://groups.google.com/group/chromium-bugs