Make it possible to write a message pipe endpoint's peer into it.
This is a nonsensical thing to do, but there's no real reason to
disallow it. (Similar nonsense can be achieve anyway.)
This requires a bit of unfortunate plumbing, but maybe it's less
unfortunate than the existing plumbing. (I also need to replace
"DispatcherTransport" with "HandleTransport", which will carry handle
rights.)
R=azani@chromium.org
BUG=fixes #767
Review URL: https://codereview.chromium.org/1943123002 .
diff --git a/mojo/edk/system/core_test_base.cc b/mojo/edk/system/core_test_base.cc
index d73706d..7df5fb7 100644
--- a/mojo/edk/system/core_test_base.cc
+++ b/mojo/edk/system/core_test_base.cc
@@ -191,7 +191,10 @@
mutex().AssertHeld();
}
- RefPtr<Dispatcher> CreateEquivalentDispatcherAndCloseImplNoLock() override {
+ RefPtr<Dispatcher> CreateEquivalentDispatcherAndCloseImplNoLock(
+ MessagePipe* /*message_pipe*/,
+ unsigned /*port*/) override {
+ CancelAllAwakablesNoLock();
return Create(info_);
}
diff --git a/mojo/edk/system/core_unittest.cc b/mojo/edk/system/core_unittest.cc
index 9395286..1b3c1fa 100644
--- a/mojo/edk/system/core_unittest.cc
+++ b/mojo/edk/system/core_unittest.cc
@@ -870,16 +870,11 @@
EXPECT_STREQ(kHello, buffer);
EXPECT_EQ(0u, num_handles);
- // Make sure that you can't pass either of the message pipe's handles over
- // itself.
+ // Make sure that you can't pass a message pipe handle over itself.
EXPECT_EQ(MOJO_RESULT_BUSY,
core()->WriteMessage(h_passing[0], UserPointer<const void>(kHello),
kHelloSize, MakeUserPointer(&h_passing[0]), 1,
MOJO_WRITE_MESSAGE_FLAG_NONE));
- EXPECT_EQ(MOJO_RESULT_INVALID_ARGUMENT,
- core()->WriteMessage(h_passing[0], UserPointer<const void>(kHello),
- kHelloSize, MakeUserPointer(&h_passing[1]), 1,
- MOJO_WRITE_MESSAGE_FLAG_NONE));
MojoHandle h_passed[2];
EXPECT_EQ(MOJO_RESULT_OK,
@@ -1603,6 +1598,57 @@
EXPECT_EQ(MOJO_RESULT_OK, core()->Close(ch));
}
+// Tests "faux leak" message pipe handle passing situations.
+TEST_F(CoreTest, MessagePipeBasicLocalHandlePassing3) {
+ {
+ MojoHandle h0 = MOJO_HANDLE_INVALID;
+ MojoHandle h1 = MOJO_HANDLE_INVALID;
+ EXPECT_EQ(MOJO_RESULT_OK,
+ core()->CreateMessagePipe(NullUserPointer(), MakeUserPointer(&h0),
+ MakeUserPointer(&h1)));
+
+ // You can send a message pipe's peer handle over itself (and nothing bad
+ // happens).
+ EXPECT_EQ(
+ MOJO_RESULT_OK,
+ core()->WriteMessage(h0, NullUserPointer(), 0, MakeUserPointer(&h1), 1,
+ MOJO_WRITE_MESSAGE_FLAG_NONE));
+
+ // Of course, there's nothing to do afterwards except close the handle you
+ // have left.
+ EXPECT_EQ(MOJO_RESULT_OK, core()->Close(h0));
+ }
+
+ {
+ MojoHandle h0 = MOJO_HANDLE_INVALID;
+ MojoHandle h1 = MOJO_HANDLE_INVALID;
+ EXPECT_EQ(MOJO_RESULT_OK,
+ core()->CreateMessagePipe(NullUserPointer(), MakeUserPointer(&h0),
+ MakeUserPointer(&h1)));
+
+ MojoHandle h_passed[2] = {MOJO_HANDLE_INVALID, MOJO_HANDLE_INVALID};
+ EXPECT_EQ(MOJO_RESULT_OK,
+ core()->CreateMessagePipe(NullUserPointer(),
+ MakeUserPointer(&h_passed[0]),
+ MakeUserPointer(&h_passed[1])));
+
+ // You can also write |h1| into some other message pipe.
+ EXPECT_EQ(MOJO_RESULT_OK,
+ core()->WriteMessage(h_passed[0], NullUserPointer(), 0,
+ MakeUserPointer(&h1), 1,
+ MOJO_WRITE_MESSAGE_FLAG_NONE));
+
+ // And then write both ends of that message pipe to |h0|.
+ EXPECT_EQ(MOJO_RESULT_OK,
+ core()->WriteMessage(h0, NullUserPointer(), 0,
+ MakeUserPointer(h_passed), 2,
+ MOJO_WRITE_MESSAGE_FLAG_NONE));
+
+ // Again, nothing bad happens, but again you can only close |h0|.
+ EXPECT_EQ(MOJO_RESULT_OK, core()->Close(h0));
+ }
+}
+
struct TestAsyncWaiter {
TestAsyncWaiter() : result(MOJO_RESULT_UNKNOWN) {}
diff --git a/mojo/edk/system/data_pipe_consumer_dispatcher.cc b/mojo/edk/system/data_pipe_consumer_dispatcher.cc
index 521456e..cdf553f 100644
--- a/mojo/edk/system/data_pipe_consumer_dispatcher.cc
+++ b/mojo/edk/system/data_pipe_consumer_dispatcher.cc
@@ -72,9 +72,13 @@
}
RefPtr<Dispatcher>
-DataPipeConsumerDispatcher::CreateEquivalentDispatcherAndCloseImplNoLock() {
+DataPipeConsumerDispatcher::CreateEquivalentDispatcherAndCloseImplNoLock(
+ MessagePipe* /*message_pipe*/,
+ unsigned /*port*/) {
mutex().AssertHeld();
+ CancelAllAwakablesNoLock();
+
auto dispatcher = DataPipeConsumerDispatcher::Create();
dispatcher->Init(std::move(data_pipe_));
return dispatcher;
diff --git a/mojo/edk/system/data_pipe_consumer_dispatcher.h b/mojo/edk/system/data_pipe_consumer_dispatcher.h
index ba69a35..aa4455a 100644
--- a/mojo/edk/system/data_pipe_consumer_dispatcher.h
+++ b/mojo/edk/system/data_pipe_consumer_dispatcher.h
@@ -46,8 +46,9 @@
// |Dispatcher| protected methods:
void CancelAllAwakablesNoLock() override;
void CloseImplNoLock() override;
- util::RefPtr<Dispatcher> CreateEquivalentDispatcherAndCloseImplNoLock()
- override;
+ util::RefPtr<Dispatcher> CreateEquivalentDispatcherAndCloseImplNoLock(
+ MessagePipe* message_pipe,
+ unsigned port) override;
MojoResult SetDataPipeConsumerOptionsImplNoLock(
UserPointer<const MojoDataPipeConsumerOptions> options) override;
MojoResult GetDataPipeConsumerOptionsImplNoLock(
diff --git a/mojo/edk/system/data_pipe_producer_dispatcher.cc b/mojo/edk/system/data_pipe_producer_dispatcher.cc
index bfa7646..e89f44f 100644
--- a/mojo/edk/system/data_pipe_producer_dispatcher.cc
+++ b/mojo/edk/system/data_pipe_producer_dispatcher.cc
@@ -72,9 +72,13 @@
}
RefPtr<Dispatcher>
-DataPipeProducerDispatcher::CreateEquivalentDispatcherAndCloseImplNoLock() {
+DataPipeProducerDispatcher::CreateEquivalentDispatcherAndCloseImplNoLock(
+ MessagePipe* /*message_pipe*/,
+ unsigned /*port*/) {
mutex().AssertHeld();
+ CancelAllAwakablesNoLock();
+
auto dispatcher = DataPipeProducerDispatcher::Create();
dispatcher->Init(std::move(data_pipe_));
return dispatcher;
diff --git a/mojo/edk/system/data_pipe_producer_dispatcher.h b/mojo/edk/system/data_pipe_producer_dispatcher.h
index 51675e7..c024c18 100644
--- a/mojo/edk/system/data_pipe_producer_dispatcher.h
+++ b/mojo/edk/system/data_pipe_producer_dispatcher.h
@@ -46,8 +46,9 @@
// |Dispatcher| protected methods:
void CancelAllAwakablesNoLock() override;
void CloseImplNoLock() override;
- util::RefPtr<Dispatcher> CreateEquivalentDispatcherAndCloseImplNoLock()
- override;
+ util::RefPtr<Dispatcher> CreateEquivalentDispatcherAndCloseImplNoLock(
+ MessagePipe* message_pipe,
+ unsigned port) override;
MojoResult SetDataPipeProducerOptionsImplNoLock(
UserPointer<const MojoDataPipeProducerOptions> options) override;
MojoResult GetDataPipeProducerOptionsImplNoLock(
diff --git a/mojo/edk/system/dispatcher.cc b/mojo/edk/system/dispatcher.cc
index 386fa0e..f3ef810 100644
--- a/mojo/edk/system/dispatcher.cc
+++ b/mojo/edk/system/dispatcher.cc
@@ -526,13 +526,14 @@
CloseImplNoLock();
}
-RefPtr<Dispatcher> Dispatcher::CreateEquivalentDispatcherAndCloseNoLock() {
+RefPtr<Dispatcher> Dispatcher::CreateEquivalentDispatcherAndCloseNoLock(
+ MessagePipe* message_pipe,
+ unsigned port) {
mutex_.AssertHeld();
DCHECK(!is_closed_);
is_closed_ = true;
- CancelAllAwakablesNoLock();
- return CreateEquivalentDispatcherAndCloseImplNoLock();
+ return CreateEquivalentDispatcherAndCloseImplNoLock(message_pipe, port);
}
void Dispatcher::StartSerialize(Channel* channel,
diff --git a/mojo/edk/system/dispatcher.h b/mojo/edk/system/dispatcher.h
index f22765b..ff8ba87 100644
--- a/mojo/edk/system/dispatcher.h
+++ b/mojo/edk/system/dispatcher.h
@@ -35,15 +35,16 @@
namespace system {
+class Awakable;
class Channel;
class Core;
class Dispatcher;
class DispatcherTransport;
class HandleTable;
class LocalMessagePipeEndpoint;
+class MessagePipe;
class ProxyMessagePipeEndpoint;
class TransportData;
-class Awakable;
using DispatcherVector = std::vector<util::RefPtr<Dispatcher>>;
@@ -259,9 +260,15 @@
virtual void CancelAllAwakablesNoLock() MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
virtual void CloseImplNoLock() MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
- virtual util::RefPtr<Dispatcher>
- CreateEquivalentDispatcherAndCloseImplNoLock()
- MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_) = 0;
+ // This is called by |CreateEquivalentDispatcherAndCloseNoLock()|. It should
+ // produce "close" this dispatcher and return a new one equivalent to it.
+ // Note: Probably the first thing an implementation should do is call
+ // |CancelAllAwakablesNoLock()| (or equivalent); unlike |CloseNoLock()|,
+ // |CreateEquivalentDispatcherAndCloseNoLock()| does not do this
+ // automatically.
+ virtual util::RefPtr<Dispatcher> CreateEquivalentDispatcherAndCloseImplNoLock(
+ MessagePipe* message_pipe,
+ unsigned port) MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_) = 0;
// These are to be overridden by subclasses (if necessary). They are never
// called after the dispatcher has been closed. See the descriptions of the
@@ -379,9 +386,12 @@
// dispatcher -- and close (i.e., disable) this dispatcher. I.e., this
// dispatcher will look as though it was closed, but the resource it
// represents will be assigned to the new dispatcher. This must be called
- // under the dispatcher's lock.
- util::RefPtr<Dispatcher> CreateEquivalentDispatcherAndCloseNoLock()
- MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
+ // under the dispatcher's lock. If the resulting dispatcher will be put into a
+ // message on a message pipe, then |message_pipe| will be set appropriately
+ // (otherwise, it may be null) and |port| will be set to the destination port.
+ util::RefPtr<Dispatcher> CreateEquivalentDispatcherAndCloseNoLock(
+ MessagePipe* message_pipe,
+ unsigned port) MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
// API to serialize dispatchers to a |Channel|, exposed to only
// |TransportData| (via |TransportData|). They may only be called on a
@@ -440,7 +450,7 @@
//
// Note: This class is deliberately "thin" -- no more expensive than a
// |Dispatcher*|.
-class DispatcherTransport {
+class DispatcherTransport final {
public:
DispatcherTransport() : dispatcher_(nullptr) {}
@@ -451,16 +461,15 @@
return dispatcher_->IsBusyNoLock();
}
void Close() MOJO_NOT_THREAD_SAFE { dispatcher_->CloseNoLock(); }
- util::RefPtr<Dispatcher> CreateEquivalentDispatcherAndClose()
- MOJO_NOT_THREAD_SAFE {
- return dispatcher_->CreateEquivalentDispatcherAndCloseNoLock();
+ util::RefPtr<Dispatcher> CreateEquivalentDispatcherAndClose(
+ MessagePipe* message_pipe,
+ unsigned port) MOJO_NOT_THREAD_SAFE {
+ return dispatcher_->CreateEquivalentDispatcherAndCloseNoLock(message_pipe,
+ port);
}
bool is_valid() const { return !!dispatcher_; }
- protected:
- Dispatcher* dispatcher() { return dispatcher_; }
-
private:
friend class Dispatcher::HandleTableAccess;
diff --git a/mojo/edk/system/message_pipe.cc b/mojo/edk/system/message_pipe.cc
index 26f93cb..cb8fc23 100644
--- a/mojo/edk/system/message_pipe.cc
+++ b/mojo/edk/system/message_pipe.cc
@@ -124,11 +124,8 @@
}
void MessagePipe::CancelAllAwakables(unsigned port) {
- DCHECK(port == 0 || port == 1);
-
MutexLocker locker(&mutex_);
- DCHECK(endpoints_[port]);
- endpoints_[port]->CancelAllAwakables();
+ CancelAllAwakablesNoLock(port);
}
void MessagePipe::Close(unsigned port) {
@@ -286,6 +283,13 @@
return true;
}
+void MessagePipe::CancelAllAwakablesNoLock(unsigned port) {
+ DCHECK(port == 0 || port == 1);
+ mutex_.AssertHeld();
+ DCHECK(endpoints_[port]);
+ endpoints_[port]->CancelAllAwakables();
+}
+
bool MessagePipe::OnReadMessage(unsigned port, MessageInTransit* message) {
MutexLocker locker(&mutex_);
@@ -355,27 +359,6 @@
std::vector<DispatcherTransport>* transports) {
DCHECK(!message->has_dispatchers());
- // You're not allowed to send either handle to a message pipe over the message
- // pipe, so check for this. (The case of trying to write a handle to itself is
- // taken care of by |Core|. That case kind of makes sense, but leads to
- // complications if, e.g., both sides try to do the same thing with their
- // respective handles simultaneously. The other case, of trying to write the
- // peer handle to a handle, doesn't make sense -- since no handle will be
- // available to read the message from.)
- for (size_t i = 0; i < transports->size(); i++) {
- if (!(*transports)[i].is_valid())
- continue;
- if ((*transports)[i].GetType() == Dispatcher::Type::MESSAGE_PIPE) {
- MessagePipeDispatcherTransport mp_transport((*transports)[i]);
- if (mp_transport.GetMessagePipe() == this) {
- // The other case should have been disallowed by |Core|. (Note: |port|
- // is the peer port of the handle given to |WriteMessage()|.)
- DCHECK_EQ(mp_transport.GetPort(), port);
- return MOJO_RESULT_INVALID_ARGUMENT;
- }
- }
- }
-
// Clone the dispatchers and attach them to the message. (This must be done as
// a separate loop, since we want to leave the dispatchers alone on failure.)
std::unique_ptr<DispatcherVector> dispatchers(new DispatcherVector());
@@ -383,7 +366,7 @@
for (size_t i = 0; i < transports->size(); i++) {
if ((*transports)[i].is_valid()) {
dispatchers->push_back(
- (*transports)[i].CreateEquivalentDispatcherAndClose());
+ (*transports)[i].CreateEquivalentDispatcherAndClose(this, port));
} else {
LOG(WARNING) << "Enqueueing null dispatcher";
dispatchers->push_back(nullptr);
diff --git a/mojo/edk/system/message_pipe.h b/mojo/edk/system/message_pipe.h
index d54ba7c..4cffa35 100644
--- a/mojo/edk/system/message_pipe.h
+++ b/mojo/edk/system/message_pipe.h
@@ -117,6 +117,12 @@
size_t* actual_size,
std::vector<platform::ScopedPlatformHandle>* platform_handles);
+ // This "implements" |CancelAllAwakables()|, but assumes that |mutex_| is
+ // already held. This is for use by
+ // |MessagePipeDispatcher::CreateEquivalentDispatcherAndCloseImplNoLock()|.
+ void CancelAllAwakablesNoLock(unsigned port)
+ MOJO_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
+
// |ChannelEndpointClient| methods:
bool OnReadMessage(unsigned port, MessageInTransit* message) override;
void OnDetachFromChannel(unsigned port) override;
diff --git a/mojo/edk/system/message_pipe_dispatcher.cc b/mojo/edk/system/message_pipe_dispatcher.cc
index 005b094..a0d5d02 100644
--- a/mojo/edk/system/message_pipe_dispatcher.cc
+++ b/mojo/edk/system/message_pipe_dispatcher.cc
@@ -133,9 +133,22 @@
}
RefPtr<Dispatcher>
-MessagePipeDispatcher::CreateEquivalentDispatcherAndCloseImplNoLock() {
+MessagePipeDispatcher::CreateEquivalentDispatcherAndCloseImplNoLock(
+ MessagePipe* message_pipe,
+ unsigned port) {
mutex().AssertHeld();
+ // "We" are being sent over our peer.
+ if (message_pipe == message_pipe_.get()) {
+ // A message pipe dispatcher can't be sent over itself (this should be
+ // disallowed by |Core|). Note that |port| is the destination port.
+ DCHECK_EQ(port, port_);
+ // In this case, |message_pipe_|'s mutex should already be held!
+ message_pipe_->CancelAllAwakablesNoLock(port_);
+ } else {
+ CancelAllAwakablesNoLock();
+ }
+
// TODO(vtl): Currently, there are no options, so we just use
// |kDefaultCreateOptions|. Eventually, we'll have to duplicate the options
// too.
@@ -220,14 +233,5 @@
return rv;
}
-// MessagePipeDispatcherTransport ----------------------------------------------
-
-MessagePipeDispatcherTransport::MessagePipeDispatcherTransport(
- DispatcherTransport transport)
- : DispatcherTransport(transport) {
- DCHECK_EQ(message_pipe_dispatcher()->GetType(),
- Dispatcher::Type::MESSAGE_PIPE);
-}
-
} // namespace system
} // namespace mojo
diff --git a/mojo/edk/system/message_pipe_dispatcher.h b/mojo/edk/system/message_pipe_dispatcher.h
index be86377..8eb9d0c 100644
--- a/mojo/edk/system/message_pipe_dispatcher.h
+++ b/mojo/edk/system/message_pipe_dispatcher.h
@@ -16,7 +16,6 @@
class ChannelEndpoint;
class MessagePipe;
-class MessagePipeDispatcherTransport;
// This is the |Dispatcher| implementation for message pipes (created by the
// Mojo primitive |MojoCreateMessagePipe()|). This class is thread-safe.
@@ -64,8 +63,6 @@
size_t size);
private:
- friend class MessagePipeDispatcherTransport;
-
MessagePipeDispatcher();
~MessagePipeDispatcher() override;
@@ -80,8 +77,9 @@
// |Dispatcher| protected methods:
void CancelAllAwakablesNoLock() override;
void CloseImplNoLock() override;
- util::RefPtr<Dispatcher> CreateEquivalentDispatcherAndCloseImplNoLock()
- override;
+ util::RefPtr<Dispatcher> CreateEquivalentDispatcherAndCloseImplNoLock(
+ MessagePipe* message_pipe,
+ unsigned port) override;
MojoResult WriteMessageImplNoLock(
UserPointer<const void> bytes,
uint32_t num_bytes,
@@ -117,23 +115,6 @@
MOJO_DISALLOW_COPY_AND_ASSIGN(MessagePipeDispatcher);
};
-class MessagePipeDispatcherTransport : public DispatcherTransport {
- public:
- explicit MessagePipeDispatcherTransport(DispatcherTransport transport);
-
- MessagePipe* GetMessagePipe() {
- return message_pipe_dispatcher()->GetMessagePipeNoLock();
- }
- unsigned GetPort() { return message_pipe_dispatcher()->GetPortNoLock(); }
-
- private:
- MessagePipeDispatcher* message_pipe_dispatcher() {
- return static_cast<MessagePipeDispatcher*>(dispatcher());
- }
-
- // Copy and assign allowed.
-};
-
} // namespace system
} // namespace mojo
diff --git a/mojo/edk/system/mock_simple_dispatcher.cc b/mojo/edk/system/mock_simple_dispatcher.cc
index bd8b283..a1f080f 100644
--- a/mojo/edk/system/mock_simple_dispatcher.cc
+++ b/mojo/edk/system/mock_simple_dispatcher.cc
@@ -66,8 +66,10 @@
MockSimpleDispatcher::~MockSimpleDispatcher() {}
RefPtr<Dispatcher>
-MockSimpleDispatcher::CreateEquivalentDispatcherAndCloseImplNoLock()
- MOJO_NO_THREAD_SAFETY_ANALYSIS {
+MockSimpleDispatcher::CreateEquivalentDispatcherAndCloseImplNoLock(
+ MessagePipe* /*message_pipe*/,
+ unsigned /*port*/) MOJO_NO_THREAD_SAFETY_ANALYSIS {
+ CancelAllAwakablesNoLock();
return MakeRefCounted<MockSimpleDispatcher>(state_);
}
diff --git a/mojo/edk/system/mock_simple_dispatcher.h b/mojo/edk/system/mock_simple_dispatcher.h
index 9776bd6..a578248 100644
--- a/mojo/edk/system/mock_simple_dispatcher.h
+++ b/mojo/edk/system/mock_simple_dispatcher.h
@@ -37,8 +37,9 @@
explicit MockSimpleDispatcher(const HandleSignalsState& state);
~MockSimpleDispatcher() override;
- util::RefPtr<Dispatcher> CreateEquivalentDispatcherAndCloseImplNoLock()
- override;
+ util::RefPtr<Dispatcher> CreateEquivalentDispatcherAndCloseImplNoLock(
+ MessagePipe* message_pipe,
+ unsigned port) override;
// |Dispatcher| override:
HandleSignalsState GetHandleSignalsStateImplNoLock() const override;
diff --git a/mojo/edk/system/platform_handle_dispatcher.cc b/mojo/edk/system/platform_handle_dispatcher.cc
index f2c6e72..93d2b5c 100644
--- a/mojo/edk/system/platform_handle_dispatcher.cc
+++ b/mojo/edk/system/platform_handle_dispatcher.cc
@@ -86,8 +86,11 @@
}
RefPtr<Dispatcher>
-PlatformHandleDispatcher::CreateEquivalentDispatcherAndCloseImplNoLock() {
+PlatformHandleDispatcher::CreateEquivalentDispatcherAndCloseImplNoLock(
+ MessagePipe* /*message_pipe*/,
+ unsigned /*port*/) {
mutex().AssertHeld();
+ CancelAllAwakablesNoLock();
return Create(platform_handle_.Pass());
}
diff --git a/mojo/edk/system/platform_handle_dispatcher.h b/mojo/edk/system/platform_handle_dispatcher.h
index 5190927..577323b 100644
--- a/mojo/edk/system/platform_handle_dispatcher.h
+++ b/mojo/edk/system/platform_handle_dispatcher.h
@@ -46,8 +46,9 @@
// |Dispatcher| protected methods:
void CloseImplNoLock() override;
- util::RefPtr<Dispatcher> CreateEquivalentDispatcherAndCloseImplNoLock()
- override;
+ util::RefPtr<Dispatcher> CreateEquivalentDispatcherAndCloseImplNoLock(
+ MessagePipe* message_pipe,
+ unsigned port) override;
void StartSerializeImplNoLock(Channel* channel,
size_t* max_size,
size_t* max_platform_handles) override
diff --git a/mojo/edk/system/platform_handle_dispatcher_unittest.cc b/mojo/edk/system/platform_handle_dispatcher_unittest.cc
index 232c7df..938c220 100644
--- a/mojo/edk/system/platform_handle_dispatcher_unittest.cc
+++ b/mojo/edk/system/platform_handle_dispatcher_unittest.cc
@@ -102,7 +102,8 @@
EXPECT_EQ(Dispatcher::Type::PLATFORM_HANDLE, transport.GetType());
EXPECT_FALSE(transport.IsBusy());
- auto generic_dispatcher = transport.CreateEquivalentDispatcherAndClose();
+ auto generic_dispatcher =
+ transport.CreateEquivalentDispatcherAndClose(nullptr, 0u);
ASSERT_TRUE(generic_dispatcher);
transport.End();
diff --git a/mojo/edk/system/shared_buffer_dispatcher.cc b/mojo/edk/system/shared_buffer_dispatcher.cc
index 3ea46d80..ee428cd 100644
--- a/mojo/edk/system/shared_buffer_dispatcher.cc
+++ b/mojo/edk/system/shared_buffer_dispatcher.cc
@@ -216,8 +216,13 @@
}
RefPtr<Dispatcher>
-SharedBufferDispatcher::CreateEquivalentDispatcherAndCloseImplNoLock() {
+SharedBufferDispatcher::CreateEquivalentDispatcherAndCloseImplNoLock(
+ MessagePipe* /*message_pipe*/,
+ unsigned /*port*/) {
mutex().AssertHeld();
+
+ CancelAllAwakablesNoLock();
+
DCHECK(shared_buffer_);
return CreateInternal(std::move(shared_buffer_));
}
diff --git a/mojo/edk/system/shared_buffer_dispatcher.h b/mojo/edk/system/shared_buffer_dispatcher.h
index 3f2f6e7..0286520 100644
--- a/mojo/edk/system/shared_buffer_dispatcher.h
+++ b/mojo/edk/system/shared_buffer_dispatcher.h
@@ -87,8 +87,9 @@
// |Dispatcher| protected methods:
void CloseImplNoLock() override;
- util::RefPtr<Dispatcher> CreateEquivalentDispatcherAndCloseImplNoLock()
- override;
+ util::RefPtr<Dispatcher> CreateEquivalentDispatcherAndCloseImplNoLock(
+ MessagePipe* message_pipe,
+ unsigned port) override;
MojoResult DuplicateBufferHandleImplNoLock(
UserPointer<const MojoDuplicateBufferHandleOptions> options,
util::RefPtr<Dispatcher>* new_dispatcher) override;