OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "mojo/edk/system/routed_raw_channel.h" | 5 #include "mojo/edk/system/routed_raw_channel.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "mojo/edk/embedder/embedder_internal.h" | 9 #include "mojo/edk/embedder/embedder_internal.h" |
10 | 10 |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
52 ++i; | 52 ++i; |
53 } | 53 } |
54 } | 54 } |
55 | 55 |
56 if (close_routes_.find(route_id) != close_routes_.end()) | 56 if (close_routes_.find(route_id) != close_routes_.end()) |
57 delegate->OnError(ERROR_READ_SHUTDOWN); | 57 delegate->OnError(ERROR_READ_SHUTDOWN); |
58 } | 58 } |
59 | 59 |
60 void RoutedRawChannel::RemoveRoute(uint64_t route_id) { | 60 void RoutedRawChannel::RemoveRoute(uint64_t route_id) { |
61 DCHECK(internal::g_io_thread_task_runner->RunsTasksOnCurrentThread()); | 61 DCHECK(internal::g_io_thread_task_runner->RunsTasksOnCurrentThread()); |
62 CHECK(routes_.find(route_id) != routes_.end()); | 62 // We don't check that routes_ contains route_id because it's possible for it |
| 63 // to not have been added yet (i.e. it's waiting to be added later down the |
| 64 // call stack). |
63 routes_.erase(route_id); | 65 routes_.erase(route_id); |
64 | 66 |
65 // Only send a message to the other side to close the route if we hadn't | 67 // Only send a message to the other side to close the route if we hadn't |
66 // received a close route message. Otherwise they would keep going back and | 68 // received a close route message. Otherwise they would keep going back and |
67 // forth. | 69 // forth. |
68 if (close_routes_.find(route_id) != close_routes_.end()) { | 70 if (close_routes_.find(route_id) != close_routes_.end()) { |
69 close_routes_.erase(route_id); | 71 close_routes_.erase(route_id); |
70 } else if (channel_) { | 72 } else if (channel_) { |
71 // Default route id of 0 to reach the other side's RoutedRawChannel. | 73 // Default route id of 0 to reach the other side's RoutedRawChannel. |
72 char message_data[sizeof(uint64_t)]; | 74 char message_data[sizeof(uint64_t)]; |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
126 memcpy(&msg->message[0], message_view.main_buffer(), | 128 memcpy(&msg->message[0], message_view.main_buffer(), |
127 message_view.total_size()); | 129 message_view.total_size()); |
128 msg->handles = platform_handles.Pass(); | 130 msg->handles = platform_handles.Pass(); |
129 pending_messages_.push_back(msg.Pass()); | 131 pending_messages_.push_back(msg.Pass()); |
130 } | 132 } |
131 } | 133 } |
132 | 134 |
133 void RoutedRawChannel::OnError(Error error) { | 135 void RoutedRawChannel::OnError(Error error) { |
134 DCHECK(internal::g_io_thread_task_runner->RunsTasksOnCurrentThread()); | 136 DCHECK(internal::g_io_thread_task_runner->RunsTasksOnCurrentThread()); |
135 | 137 |
136 // This needs to match non-multiplexed MessagePipeDispatcher's destruction of | 138 // Note: we must ensure we don't call RawChannel::Shutdown until after we've |
137 // the channel only when read errors occur. | 139 // called OnError on each route's delegate. |
138 if (error != ERROR_WRITE || routes_.empty()) { | 140 for (auto it = routes_.begin(); it != routes_.end();) { |
139 channel_->Shutdown(); | 141 // The delegate might call RemoveRoute in their OnError implementation which |
140 channel_ = nullptr; | 142 // would invalidate |it|. So increment it first. |
| 143 auto cur_it = it++; |
| 144 cur_it->second->OnError(error); |
141 } | 145 } |
142 | 146 |
143 if (routes_.empty()) { | 147 if (routes_.empty()) { |
| 148 channel_->Shutdown(); |
| 149 channel_ = nullptr; |
144 delete this; | 150 delete this; |
145 return; | 151 return; |
146 } | 152 } |
147 | |
148 for (auto it = routes_.begin(); it != routes_.end();) { | |
149 // Handle the delegate calling RemoveRoute in this call. | |
150 auto cur_it = it++; | |
151 cur_it->second->OnError(error); | |
152 } | |
153 } | 153 } |
154 | 154 |
155 } // namespace edk | 155 } // namespace edk |
156 } // namespace mojo | 156 } // namespace mojo |
OLD | NEW |