summaryrefslogtreecommitdiffstats
path: root/chrome/browser/worker_host
diff options
context:
space:
mode:
authorjam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-09-21 22:13:31 +0000
committerjam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-09-21 22:13:31 +0000
commit4d5a37cdab721adbb9f64a3a0a11be16df8f91e1 (patch)
tree3f64283331452a383f94f6890ba6e812b2776f9c /chrome/browser/worker_host
parentb78e168b1640e456e1fc5a1ca8956a4a50c7df94 (diff)
downloadchromium_src-4d5a37cdab721adbb9f64a3a0a11be16df8f91e1.zip
chromium_src-4d5a37cdab721adbb9f64a3a0a11be16df8f91e1.tar.gz
chromium_src-4d5a37cdab721adbb9f64a3a0a11be16df8f91e1.tar.bz2
Fix race condition with message ports being dropped if sent before a worker starts.
BUG=22315 TEST=covered by worker-messageport-gc.html Review URL: http://codereview.chromium.org/208045 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@26749 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/worker_host')
-rw-r--r--chrome/browser/worker_host/message_port_dispatcher.cc11
-rw-r--r--chrome/browser/worker_host/message_port_dispatcher.h5
-rw-r--r--chrome/browser/worker_host/worker_process_host.cc53
3 files changed, 45 insertions, 24 deletions
diff --git a/chrome/browser/worker_host/message_port_dispatcher.cc b/chrome/browser/worker_host/message_port_dispatcher.cc
index 41ebc37..c6e992d 100644
--- a/chrome/browser/worker_host/message_port_dispatcher.cc
+++ b/chrome/browser/worker_host/message_port_dispatcher.cc
@@ -193,8 +193,9 @@ void MessagePortDispatcher::OnQueueMessages(int message_port_id) {
}
MessagePort& port = message_ports_[message_port_id];
- port.queue_messages = true;
port.sender->Send(new WorkerProcessMsg_MessagesQueued(port.route_id));
+ port.queue_messages = true;
+ port.sender = NULL;
}
void MessagePortDispatcher::OnSendQueuedMessages(
@@ -212,6 +213,14 @@ void MessagePortDispatcher::OnSendQueuedMessages(
port.queued_messages.insert(port.queued_messages.begin(),
queued_messages.begin(),
queued_messages.end());
+ SendQueuedMessagesIfPossible(message_port_id);
+}
+
+void MessagePortDispatcher::SendQueuedMessagesIfPossible(int message_port_id) {
+ MessagePort& port = message_ports_[message_port_id];
+ if (port.queue_messages || !port.sender)
+ return;
+
for (QueuedMessages::iterator iter = port.queued_messages.begin();
iter != port.queued_messages.end(); ++iter) {
PostMessageTo(message_port_id, iter->first, iter->second);
diff --git a/chrome/browser/worker_host/message_port_dispatcher.h b/chrome/browser/worker_host/message_port_dispatcher.h
index c728f38..21be0c6 100644
--- a/chrome/browser/worker_host/message_port_dispatcher.h
+++ b/chrome/browser/worker_host/message_port_dispatcher.h
@@ -28,12 +28,17 @@ class MessagePortDispatcher : public NotificationObserver {
CallbackWithReturnValue<int>::Type* next_routing_id,
bool* message_was_ok);
+ // Updates the information needed to reach a message port when it's sent to a
+ // (possibly different) process.
void UpdateMessagePort(
int message_port_id,
IPC::Message::Sender* sender,
int routing_id,
CallbackWithReturnValue<int>::Type* next_routing_id);
+ // Attempts to send the queued messages for a message port.
+ void SendQueuedMessagesIfPossible(int message_port_id);
+
bool Send(IPC::Message* message);
private:
diff --git a/chrome/browser/worker_host/worker_process_host.cc b/chrome/browser/worker_host/worker_process_host.cc
index 9570743..b3a5b1c 100644
--- a/chrome/browser/worker_host/worker_process_host.cc
+++ b/chrome/browser/worker_host/worker_process_host.cc
@@ -228,33 +228,40 @@ void WorkerProcessHost::RelayMessage(
IPC::Message::Sender* sender,
int route_id,
CallbackWithReturnValue<int>::Type* next_route_id) {
- IPC::Message* new_message;
- if (message.type() == WorkerMsg_PostMessage::ID) {
- // We want to send the receiver a routing id for the new channel, so
- // crack the message first.
- string16 msg;
- std::vector<int> sent_message_port_ids;
- std::vector<int> new_routing_ids;
- if (!WorkerMsg_PostMessage::Read(
- &message, &msg, &sent_message_port_ids, &new_routing_ids)) {
- return;
- }
- DCHECK(sent_message_port_ids.size() == new_routing_ids.size());
+ if (message.type() != WorkerMsg_PostMessage::ID) {
+ IPC::Message* new_message = new IPC::Message(message);
+ new_message->set_routing_id(route_id);
+ sender->Send(new_message);
+ return;
+ }
- for (size_t i = 0; i < sent_message_port_ids.size(); ++i) {
- new_routing_ids[i] = next_route_id->Run();
- MessagePortDispatcher::GetInstance()->UpdateMessagePort(
- sent_message_port_ids[i], sender, new_routing_ids[i], next_route_id);
- }
+ // We want to send the receiver a routing id for the new channel, so
+ // crack the message first.
+ string16 msg;
+ std::vector<int> sent_message_port_ids;
+ std::vector<int> new_routing_ids;
+ if (!WorkerMsg_PostMessage::Read(
+ &message, &msg, &sent_message_port_ids, &new_routing_ids)) {
+ return;
+ }
+ DCHECK(sent_message_port_ids.size() == new_routing_ids.size());
- new_message = new WorkerMsg_PostMessage(
- route_id, msg, sent_message_port_ids, new_routing_ids);
- } else {
- new_message = new IPC::Message(message);
- new_message->set_routing_id(route_id);
+ for (size_t i = 0; i < sent_message_port_ids.size(); ++i) {
+ new_routing_ids[i] = next_route_id->Run();
+ MessagePortDispatcher::GetInstance()->UpdateMessagePort(
+ sent_message_port_ids[i], sender, new_routing_ids[i], next_route_id);
}
- sender->Send(new_message);
+ sender->Send(new WorkerMsg_PostMessage(
+ route_id, msg, sent_message_port_ids, new_routing_ids));
+
+ // Send any queued messages to the sent message ports. We can only do this
+ // after sending the above message, since it's the one that sets up the
+ // message port route which the queued messages are sent to.
+ for (size_t i = 0; i < sent_message_port_ids.size(); ++i) {
+ MessagePortDispatcher::GetInstance()->
+ SendQueuedMessagesIfPossible(sent_message_port_ids[i]);
+ }
}
void WorkerProcessHost::SenderShutdown(IPC::Message::Sender* sender) {