summaryrefslogtreecommitdiffstats
path: root/mojo
diff options
context:
space:
mode:
authorsammc <sammc@chromium.org>2016-03-13 23:16:09 -0700
committerCommit bot <commit-bot@chromium.org>2016-03-14 06:17:09 +0000
commit4153ea34f326b4868d1233656a4774c3f213a781 (patch)
tree898fa791ab1be2edff923c473425c3b3cd2385b0 /mojo
parentbc660067f6322d4ad1383336cb5afaae7d70fc91 (diff)
downloadchromium_src-4153ea34f326b4868d1233656a4774c3f213a781.zip
chromium_src-4153ea34f326b4868d1233656a4774c3f213a781.tar.gz
chromium_src-4153ea34f326b4868d1233656a4774c3f213a781.tar.bz2
Change mojo::Watcher to survive closing a handle and cancelling.
Currently, if a handle is closed while a Watcher is watching it, its callback will notify it that the watch has been cancelled. However, if the Watcher is explicitly cancelled after the handle is closed but before the callback is called, it will attempt to call MojoCancelWatch() on the closed handle and DCHECK that it succeeds. This changes the DCHECK to also accept MOJO_ERROR_INVALID_ARGUMENT. Review URL: https://codereview.chromium.org/1795193005 Cr-Commit-Position: refs/heads/master@{#380936}
Diffstat (limited to 'mojo')
-rw-r--r--mojo/public/cpp/system/tests/watcher_unittest.cc20
-rw-r--r--mojo/public/cpp/system/watcher.cc4
2 files changed, 23 insertions, 1 deletions
diff --git a/mojo/public/cpp/system/tests/watcher_unittest.cc b/mojo/public/cpp/system/tests/watcher_unittest.cc
index ea78a56..f72f495 100644
--- a/mojo/public/cpp/system/tests/watcher_unittest.cc
+++ b/mojo/public/cpp/system/tests/watcher_unittest.cc
@@ -182,5 +182,25 @@ TEST_F(WatcherTest, NotifyOnMessageLoopDestruction) {
b_watcher.Cancel();
}
+TEST_F(WatcherTest, CloseAndCancel) {
+ ScopedMessagePipeHandle a, b;
+ CreateMessagePipe(nullptr, &a, &b);
+
+ Watcher b_watcher;
+ EXPECT_EQ(MOJO_RESULT_OK,
+ b_watcher.Start(b.get(), MOJO_HANDLE_SIGNAL_READABLE,
+ OnReady([](MojoResult result) { FAIL(); })));
+ EXPECT_TRUE(b_watcher.IsWatching());
+
+ // This should trigger the watcher above...
+ b.reset();
+ // ...but the watcher is cancelled first.
+ b_watcher.Cancel();
+
+ EXPECT_FALSE(b_watcher.IsWatching());
+
+ base::RunLoop().RunUntilIdle();
+}
+
} // namespace
} // namespace mojo
diff --git a/mojo/public/cpp/system/watcher.cc b/mojo/public/cpp/system/watcher.cc
index ad965ff..5723533 100644
--- a/mojo/public/cpp/system/watcher.cc
+++ b/mojo/public/cpp/system/watcher.cc
@@ -96,7 +96,9 @@ void Watcher::Cancel() {
MojoResult result =
MojoCancelWatch(handle_.value(), reinterpret_cast<uintptr_t>(this));
message_loop_observer_.reset();
- DCHECK_EQ(result, MOJO_RESULT_OK);
+ // |result| may be MOJO_RESULT_INVALID_ARGUMENT if |handle_| has closed, but
+ // OnHandleReady has not yet been called.
+ DCHECK(result == MOJO_RESULT_INVALID_ARGUMENT || result == MOJO_RESULT_OK);
handle_.set_value(kInvalidHandleValue);
callback_.Reset();
}