Adding MOJO_HANDLE_SIGNAL_PEER_CLOSED to be notified when a peer is closed.
BUG=436227
R=viettrungluu@chromium.org
Review URL: https://codereview.chromium.org/741503003
diff --git a/mojo/edk/system/channel_unittest.cc b/mojo/edk/system/channel_unittest.cc
index 68b1315..e84ab5b 100644
--- a/mojo/edk/system/channel_unittest.cc
+++ b/mojo/edk/system/channel_unittest.cc
@@ -243,8 +243,8 @@
waiter.Wait(MOJO_DEADLINE_INDEFINITE, nullptr));
HandleSignalsState hss;
mp->RemoveWaiter(0, &waiter, &hss);
- EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(0u, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals);
mp->Close(0);
@@ -279,8 +279,8 @@
HandleSignalsState hss;
EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
mp->AddWaiter(0, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 123, &hss));
- EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(0u, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals);
mp->Close(0);
diff --git a/mojo/edk/system/core_unittest.cc b/mojo/edk/system/core_unittest.cc
index 3969322..51a4022 100644
--- a/mojo/edk/system/core_unittest.cc
+++ b/mojo/edk/system/core_unittest.cc
@@ -18,6 +18,9 @@
const MojoHandleSignalsState kEmptyMojoHandleSignalsState = {0u, 0u};
const MojoHandleSignalsState kFullMojoHandleSignalsState = {~0u, ~0u};
+const MojoHandleSignals kAllSignals = MOJO_HANDLE_SIGNAL_READABLE |
+ MOJO_HANDLE_SIGNAL_WRITABLE |
+ MOJO_HANDLE_SIGNAL_PEER_CLOSED;
typedef test::CoreTestBase CoreTest;
@@ -545,11 +548,9 @@
MakeUserPointer(&result_index), MakeUserPointer(hss)));
EXPECT_EQ(static_cast<uint32_t>(-1), result_index);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss[0].satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss[0].satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss[0].satisfiable_signals);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss[1].satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss[1].satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss[1].satisfiable_signals);
// Try to read anyway.
char buffer[1] = {'a'};
@@ -568,14 +569,12 @@
EXPECT_EQ(MOJO_RESULT_OK, core()->Wait(h[0], MOJO_HANDLE_SIGNAL_WRITABLE,
1000000000, MakeUserPointer(&hss[0])));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss[0].satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss[0].satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss[0].satisfiable_signals);
hss[0] = kEmptyMojoHandleSignalsState;
EXPECT_EQ(MOJO_RESULT_OK, core()->Wait(h[1], MOJO_HANDLE_SIGNAL_WRITABLE,
1000000000, MakeUserPointer(&hss[0])));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss[0].satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss[0].satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss[0].satisfiable_signals);
// Also check that |h[1]| is writable using |WaitMany()|.
signals[0] = MOJO_HANDLE_SIGNAL_READABLE;
@@ -590,11 +589,9 @@
MakeUserPointer(hss)));
EXPECT_EQ(1u, result_index);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss[0].satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss[0].satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss[0].satisfiable_signals);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss[1].satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss[1].satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss[1].satisfiable_signals);
// Write to |h[1]|.
buffer[0] = 'b';
@@ -617,11 +614,9 @@
EXPECT_EQ(0u, result_index);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss[0].satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss[0].satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss[0].satisfiable_signals);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss[1].satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss[1].satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss[1].satisfiable_signals);
// Read from |h[0]|.
// First, get only the size.
@@ -649,8 +644,7 @@
core()->Wait(h[0], MOJO_HANDLE_SIGNAL_READABLE, 0,
MakeUserPointer(&hss[0])));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss[0].satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss[0].satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss[0].satisfiable_signals);
// Write to |h[0]|.
buffer[0] = 'd';
@@ -667,15 +661,19 @@
EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
core()->Wait(h[1], MOJO_HANDLE_SIGNAL_WRITABLE, 1000000000,
MakeUserPointer(&hss[0])));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss[0].satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss[0].satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss[0].satisfied_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss[0].satisfiable_signals);
// Check that |h[1]| is still readable (for the moment).
hss[0] = kEmptyMojoHandleSignalsState;
EXPECT_EQ(MOJO_RESULT_OK, core()->Wait(h[1], MOJO_HANDLE_SIGNAL_READABLE,
1000000000, MakeUserPointer(&hss[0])));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss[0].satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss[0].satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss[0].satisfied_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss[0].satisfiable_signals);
// Discard a message from |h[1]|.
EXPECT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED,
@@ -688,8 +686,8 @@
EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
core()->Wait(h[1], MOJO_HANDLE_SIGNAL_READABLE, 1000000000,
MakeUserPointer(&hss[0])));
- EXPECT_EQ(0u, hss[0].satisfied_signals);
- EXPECT_EQ(0u, hss[0].satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss[0].satisfied_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss[0].satisfiable_signals);
// Try writing to |h[1]|.
buffer[0] = 'e';
@@ -732,8 +730,7 @@
MakeUserPointer(&hss)));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
num_bytes = kBufferSize;
num_handles = arraysize(handles);
EXPECT_EQ(MOJO_RESULT_OK,
@@ -773,8 +770,7 @@
MakeUserPointer(&hss)));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
num_bytes = kBufferSize;
num_handles = arraysize(handles);
EXPECT_EQ(MOJO_RESULT_OK,
@@ -797,8 +793,7 @@
MakeUserPointer(&hss)));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
num_bytes = kBufferSize;
num_handles = arraysize(handles);
EXPECT_EQ(MOJO_RESULT_OK,
@@ -833,8 +828,7 @@
MakeUserPointer(&hss)));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
num_bytes = kBufferSize;
num_handles = arraysize(handles);
EXPECT_EQ(MOJO_RESULT_OK,
@@ -870,12 +864,14 @@
MOJO_RESULT_FAILED_PRECONDITION,
core()->Wait(ph, MOJO_HANDLE_SIGNAL_READABLE, 0, MakeUserPointer(&hss)));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfiable_signals);
hss = kEmptyMojoHandleSignalsState;
EXPECT_EQ(MOJO_RESULT_OK, core()->Wait(ph, MOJO_HANDLE_SIGNAL_WRITABLE, 0,
MakeUserPointer(&hss)));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfiable_signals);
// Consumer should be never-writable, and not yet readable.
hss = kFullMojoHandleSignalsState;
@@ -883,13 +879,15 @@
MOJO_RESULT_FAILED_PRECONDITION,
core()->Wait(ch, MOJO_HANDLE_SIGNAL_WRITABLE, 0, MakeUserPointer(&hss)));
EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfiable_signals);
hss = kFullMojoHandleSignalsState;
EXPECT_EQ(
MOJO_RESULT_DEADLINE_EXCEEDED,
core()->Wait(ch, MOJO_HANDLE_SIGNAL_READABLE, 0, MakeUserPointer(&hss)));
EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfiable_signals);
// Write.
signed char elements[2] = {'A', 'B'};
@@ -905,7 +903,8 @@
EXPECT_EQ(MOJO_RESULT_OK, core()->Wait(ch, MOJO_HANDLE_SIGNAL_READABLE, 0,
MakeUserPointer(&hss)));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfiable_signals);
// Peek one character.
elements[0] = -1;
@@ -1022,7 +1021,8 @@
MOJO_RESULT_DEADLINE_EXCEEDED,
core()->Wait(ch, MOJO_HANDLE_SIGNAL_READABLE, 0, MakeUserPointer(&hss)));
EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfiable_signals);
// TODO(vtl): More.
@@ -1034,8 +1034,8 @@
EXPECT_EQ(
MOJO_RESULT_FAILED_PRECONDITION,
core()->Wait(ch, MOJO_HANDLE_SIGNAL_READABLE, 0, MakeUserPointer(&hss)));
- EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(0u, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals);
EXPECT_EQ(MOJO_RESULT_OK, core()->Close(ch));
}
@@ -1075,8 +1075,7 @@
MakeUserPointer(&hss)));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
num_bytes = kBufferSize;
num_handles = arraysize(handles);
EXPECT_EQ(MOJO_RESULT_OK,
@@ -1111,7 +1110,8 @@
core()->Wait(ch_received, MOJO_HANDLE_SIGNAL_READABLE, 1000000000,
MakeUserPointer(&hss)));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfiable_signals);
num_bytes = kBufferSize;
EXPECT_EQ(MOJO_RESULT_OK,
core()->ReadData(ch_received, UserPointer<void>(buffer),
@@ -1131,8 +1131,7 @@
MakeUserPointer(&hss)));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
num_bytes = kBufferSize;
num_handles = arraysize(handles);
EXPECT_EQ(MOJO_RESULT_OK,
@@ -1167,7 +1166,8 @@
core()->Wait(ch_received, MOJO_HANDLE_SIGNAL_READABLE, 1000000000,
MakeUserPointer(&hss)));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfiable_signals);
num_bytes = kBufferSize;
EXPECT_EQ(MOJO_RESULT_OK,
core()->ReadData(ch_received, UserPointer<void>(buffer),
@@ -1225,7 +1225,8 @@
EXPECT_EQ(MOJO_RESULT_OK, core()->Wait(ch, MOJO_HANDLE_SIGNAL_READABLE,
1000000000, MakeUserPointer(&hss)));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfiable_signals);
// Make sure that |ch| can't be sent if it's in a two-phase read.
const void* read_ptr = nullptr;
@@ -1251,8 +1252,7 @@
MakeUserPointer(&hss)));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
num_bytes = kBufferSize;
num_handles = arraysize(handles);
EXPECT_EQ(MOJO_RESULT_OK,
diff --git a/mojo/edk/system/local_data_pipe.cc b/mojo/edk/system/local_data_pipe.cc
index 177b238..8b9f673 100644
--- a/mojo/edk/system/local_data_pipe.cc
+++ b/mojo/edk/system/local_data_pipe.cc
@@ -160,7 +160,10 @@
!producer_in_two_phase_write_no_lock())
rv.satisfied_signals |= MOJO_HANDLE_SIGNAL_WRITABLE;
rv.satisfiable_signals |= MOJO_HANDLE_SIGNAL_WRITABLE;
+ } else {
+ rv.satisfied_signals |= MOJO_HANDLE_SIGNAL_PEER_CLOSED;
}
+ rv.satisfiable_signals |= MOJO_HANDLE_SIGNAL_PEER_CLOSED;
return rv;
}
@@ -293,6 +296,9 @@
} else if (producer_open_no_lock()) {
rv.satisfiable_signals |= MOJO_HANDLE_SIGNAL_READABLE;
}
+ if (!producer_open_no_lock())
+ rv.satisfied_signals |= MOJO_HANDLE_SIGNAL_PEER_CLOSED;
+ rv.satisfiable_signals |= MOJO_HANDLE_SIGNAL_PEER_CLOSED;
return rv;
}
diff --git a/mojo/edk/system/local_data_pipe_unittest.cc b/mojo/edk/system/local_data_pipe_unittest.cc
index 9ba6b21..cea50a0 100644
--- a/mojo/edk/system/local_data_pipe_unittest.cc
+++ b/mojo/edk/system/local_data_pipe_unittest.cc
@@ -239,7 +239,8 @@
MOJO_RESULT_FAILED_PRECONDITION,
dp->ProducerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 12, &hss));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfiable_signals);
// Already writable.
waiter.Init();
@@ -266,7 +267,8 @@
hss = HandleSignalsState();
dp->ProducerRemoveWaiter(&waiter, &hss);
EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfiable_signals);
// Peek one element.
elements[0] = -1;
@@ -289,7 +291,8 @@
hss = HandleSignalsState();
dp->ProducerRemoveWaiter(&waiter, &hss);
EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfiable_signals);
// Do it again.
waiter.Init();
@@ -314,7 +317,8 @@
hss = HandleSignalsState();
dp->ProducerRemoveWaiter(&waiter, &hss);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfiable_signals);
// Try writing, using a two-phase write.
void* buffer = nullptr;
@@ -357,7 +361,8 @@
hss = HandleSignalsState();
dp->ProducerRemoveWaiter(&waiter, &hss);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfiable_signals);
// Write one element.
elements[0] = 123;
@@ -381,12 +386,75 @@
EXPECT_EQ(12u, context);
hss = HandleSignalsState();
dp->ProducerRemoveWaiter(&waiter, &hss);
- EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(0u, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals);
dp->ProducerClose();
}
+TEST(LocalDataPipeTest, PeerClosedWaiting) {
+ const MojoCreateDataPipeOptions options = {
+ kSizeOfOptions, // |struct_size|.
+ MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE, // |flags|.
+ static_cast<uint32_t>(sizeof(int32_t)), // |element_num_bytes|.
+ 2 * sizeof(int32_t) // |capacity_num_bytes|.
+ };
+ MojoCreateDataPipeOptions validated_options = {0};
+ EXPECT_EQ(MOJO_RESULT_OK, DataPipe::ValidateCreateOptions(
+ MakeUserPointer(&options), &validated_options));
+
+ Waiter waiter;
+ HandleSignalsState hss;
+
+ // Check MOJO_HANDLE_SIGNAL_PEER_CLOSED on producer.
+ {
+ scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
+ // Add a waiter.
+ waiter.Init();
+ ASSERT_EQ(MOJO_RESULT_OK,
+ dp->ProducerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_PEER_CLOSED, 12,
+ nullptr));
+
+ // Close the consumer.
+ dp->ConsumerClose();
+
+ // It should be signaled.
+ uint32_t context = 0;
+ EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(1000, &context));
+ EXPECT_EQ(12u, context);
+ hss = HandleSignalsState();
+ dp->ProducerRemoveWaiter(&waiter, &hss);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals);
+
+ dp->ProducerClose();
+ }
+
+ // Check MOJO_HANDLE_SIGNAL_PEER_CLOSED on consumer.
+ {
+ scoped_refptr<LocalDataPipe> dp(new LocalDataPipe(validated_options));
+ // Add a waiter.
+ waiter.Init();
+ ASSERT_EQ(MOJO_RESULT_OK,
+ dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_PEER_CLOSED, 12,
+ nullptr));
+
+ // Close the producer.
+ dp->ProducerClose();
+
+ // It should be signaled.
+ uint32_t context = 0;
+ EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(1000, &context));
+ EXPECT_EQ(12u, context);
+ hss = HandleSignalsState();
+ dp->ConsumerRemoveWaiter(&waiter, &hss);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals);
+
+ dp->ConsumerClose();
+ }
+}
+
TEST(LocalDataPipeTest, BasicConsumerWaiting) {
const MojoCreateDataPipeOptions options = {
kSizeOfOptions, // |struct_size|.
@@ -411,7 +479,8 @@
MOJO_RESULT_FAILED_PRECONDITION,
dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 12, &hss));
EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfiable_signals);
// Not yet readable.
waiter.Init();
@@ -422,7 +491,8 @@
hss = HandleSignalsState();
dp->ConsumerRemoveWaiter(&waiter, &hss);
EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfiable_signals);
// Write two elements.
int32_t elements[2] = {123, 456};
@@ -438,7 +508,8 @@
MOJO_RESULT_ALREADY_EXISTS,
dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 56, &hss));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfiable_signals);
// Discard one element.
num_bytes = static_cast<uint32_t>(1u * sizeof(elements[0]));
@@ -453,7 +524,8 @@
MOJO_RESULT_ALREADY_EXISTS,
dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 78, &hss));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfiable_signals);
// Peek one element.
elements[0] = -1;
@@ -473,7 +545,8 @@
MOJO_RESULT_ALREADY_EXISTS,
dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 78, &hss));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfiable_signals);
// Read one element.
elements[0] = -1;
@@ -506,7 +579,8 @@
hss = HandleSignalsState();
dp->ConsumerRemoveWaiter(&waiter, &hss);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfiable_signals);
// Close the producer.
dp->ProducerClose();
@@ -517,8 +591,10 @@
EXPECT_EQ(
MOJO_RESULT_ALREADY_EXISTS,
dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 12, &hss));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfied_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfiable_signals);
// Read one element.
elements[0] = -1;
@@ -537,8 +613,8 @@
EXPECT_EQ(
MOJO_RESULT_FAILED_PRECONDITION,
dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 34, &hss));
- EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(0u, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals);
dp->ConsumerClose();
}
@@ -574,7 +650,8 @@
MOJO_RESULT_ALREADY_EXISTS,
dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 12, &hss));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfiable_signals);
// Read one element.
// Request two in all-or-none mode, but only read one.
@@ -597,7 +674,8 @@
MOJO_RESULT_ALREADY_EXISTS,
dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 34, &hss));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfiable_signals);
// Read one element.
// Request three, but not in all-or-none mode.
@@ -627,8 +705,8 @@
EXPECT_EQ(56u, context);
hss = HandleSignalsState();
dp->ConsumerRemoveWaiter(&waiter, &hss);
- EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(0u, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals);
dp->ConsumerClose();
}
@@ -657,7 +735,8 @@
MOJO_RESULT_ALREADY_EXISTS,
dp->ProducerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 0, &hss));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfiable_signals);
uint32_t num_bytes = static_cast<uint32_t>(1u * sizeof(int32_t));
void* write_ptr = nullptr;
@@ -676,7 +755,8 @@
hss = HandleSignalsState();
dp->ProducerRemoveWaiter(&waiter, &hss);
EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfiable_signals);
// It shouldn't be readable yet either.
waiter.Init();
@@ -687,7 +767,8 @@
hss = HandleSignalsState();
dp->ConsumerRemoveWaiter(&waiter, &hss);
EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfiable_signals);
static_cast<int32_t*>(write_ptr)[0] = 123;
EXPECT_EQ(MOJO_RESULT_OK, dp->ProducerEndWriteData(
@@ -700,7 +781,8 @@
MOJO_RESULT_ALREADY_EXISTS,
dp->ProducerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 3, &hss));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfiable_signals);
// And readable.
waiter.Init();
@@ -709,7 +791,8 @@
MOJO_RESULT_ALREADY_EXISTS,
dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 4, &hss));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfiable_signals);
// Start another two-phase write and check that it's readable even in the
// middle of it.
@@ -728,7 +811,8 @@
MOJO_RESULT_ALREADY_EXISTS,
dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 5, &hss));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfiable_signals);
// End the two-phase write without writing anything.
EXPECT_EQ(MOJO_RESULT_OK, dp->ProducerEndWriteData(0u));
@@ -749,7 +833,8 @@
MOJO_RESULT_ALREADY_EXISTS,
dp->ProducerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 6, &hss));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfiable_signals);
// But not readable.
waiter.Init();
@@ -760,7 +845,8 @@
hss = HandleSignalsState();
dp->ConsumerRemoveWaiter(&waiter, &hss);
EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfiable_signals);
// End the two-phase read without reading anything.
EXPECT_EQ(MOJO_RESULT_OK, dp->ConsumerEndReadData(0u));
@@ -772,7 +858,8 @@
MOJO_RESULT_ALREADY_EXISTS,
dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 8, &hss));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfiable_signals);
dp->ProducerClose();
dp->ConsumerClose();
@@ -801,7 +888,8 @@
MOJO_RESULT_ALREADY_EXISTS,
dp->ProducerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 0, &hss));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfiable_signals);
// Not readable.
waiter.Init();
@@ -812,7 +900,8 @@
hss = HandleSignalsState();
dp->ConsumerRemoveWaiter(&waiter, &hss);
EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfiable_signals);
uint32_t num_bytes = static_cast<uint32_t>(sizeof(int32_t));
int32_t element = 123;
@@ -828,7 +917,8 @@
MOJO_RESULT_ALREADY_EXISTS,
dp->ProducerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 2, &hss));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfiable_signals);
// Now readable.
waiter.Init();
@@ -837,7 +927,8 @@
MOJO_RESULT_ALREADY_EXISTS,
dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 3, &hss));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfiable_signals);
// Overwrite that element.
num_bytes = static_cast<uint32_t>(sizeof(int32_t));
@@ -854,7 +945,8 @@
MOJO_RESULT_ALREADY_EXISTS,
dp->ProducerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 4, &hss));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfiable_signals);
// And still readable.
waiter.Init();
@@ -863,7 +955,8 @@
MOJO_RESULT_ALREADY_EXISTS,
dp->ConsumerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_READABLE, 5, &hss));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfiable_signals);
// Read that element.
num_bytes = static_cast<uint32_t>(sizeof(int32_t));
@@ -881,7 +974,8 @@
MOJO_RESULT_ALREADY_EXISTS,
dp->ProducerAddWaiter(&waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 6, &hss));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfiable_signals);
// No longer readable.
waiter.Init();
@@ -892,7 +986,8 @@
hss = HandleSignalsState();
dp->ConsumerRemoveWaiter(&waiter, &hss);
EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfiable_signals);
dp->ProducerClose();
dp->ConsumerClose();
diff --git a/mojo/edk/system/local_message_pipe_endpoint.cc b/mojo/edk/system/local_message_pipe_endpoint.cc
index 124241e..86d241c 100644
--- a/mojo/edk/system/local_message_pipe_endpoint.cc
+++ b/mojo/edk/system/local_message_pipe_endpoint.cc
@@ -137,7 +137,10 @@
rv.satisfied_signals |= MOJO_HANDLE_SIGNAL_WRITABLE;
rv.satisfiable_signals |=
MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE;
+ } else {
+ rv.satisfied_signals |= MOJO_HANDLE_SIGNAL_PEER_CLOSED;
}
+ rv.satisfiable_signals |= MOJO_HANDLE_SIGNAL_PEER_CLOSED;
return rv;
}
diff --git a/mojo/edk/system/message_pipe_dispatcher_unittest.cc b/mojo/edk/system/message_pipe_dispatcher_unittest.cc
index 8076a99..303ae6a 100644
--- a/mojo/edk/system/message_pipe_dispatcher_unittest.cc
+++ b/mojo/edk/system/message_pipe_dispatcher_unittest.cc
@@ -29,6 +29,10 @@
namespace system {
namespace {
+const MojoHandleSignals kAllSignals = MOJO_HANDLE_SIGNAL_READABLE |
+ MOJO_HANDLE_SIGNAL_WRITABLE |
+ MOJO_HANDLE_SIGNAL_PEER_CLOSED;
+
TEST(MessagePipeDispatcherTest, Basic) {
test::Stopwatch stopwatch;
int32_t buffer[1];
@@ -57,8 +61,7 @@
EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
d0->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 0, &hss));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
// Shouldn't need to remove the waiter (it was not added).
// Add a readable waiter to |d0|, then make it readable (by writing to
@@ -78,8 +81,7 @@
d0->RemoveWaiter(&w, &hss);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
// Try adding a readable waiter when already readable (from above).
w.Init();
@@ -88,8 +90,7 @@
d0->AddWaiter(&w, MOJO_HANDLE_SIGNAL_READABLE, 2, &hss));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
// Shouldn't need to remove the waiter (it was not added).
// Make |d0| no longer readable (by reading from it).
@@ -112,8 +113,7 @@
hss = HandleSignalsState();
d0->RemoveWaiter(&w, &hss);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
// Wait for non-zero, finite time for readability on |d0| (will time out).
w.Init();
@@ -128,11 +128,25 @@
hss = HandleSignalsState();
d0->RemoveWaiter(&w, &hss);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
+
+ // Check the peer closed signal.
+ w.Init();
+ ASSERT_EQ(MOJO_RESULT_OK,
+ d0->AddWaiter(&w, MOJO_HANDLE_SIGNAL_PEER_CLOSED, 12, nullptr));
+
+ // Close the peer.
+ EXPECT_EQ(MOJO_RESULT_OK, d1->Close());
+
+ // It should be signaled.
+ EXPECT_EQ(MOJO_RESULT_OK, w.Wait(1000, &context));
+ EXPECT_EQ(12u, context);
+ hss = HandleSignalsState();
+ d0->RemoveWaiter(&w, &hss);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals);
EXPECT_EQ(MOJO_RESULT_OK, d0->Close());
- EXPECT_EQ(MOJO_RESULT_OK, d1->Close());
}
}
@@ -238,8 +252,7 @@
d0->AddWaiter(&w, MOJO_HANDLE_SIGNAL_READABLE, 0, &hss));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
// Try reading from |d1|; should fail (nothing to read).
buffer[0] = 0;
@@ -257,8 +270,10 @@
hss = HandleSignalsState();
EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
d0->AddWaiter(&w, MOJO_HANDLE_SIGNAL_READABLE, 1, &hss));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfied_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfiable_signals);
// Read from |d0|.
buffer[0] = 0;
@@ -275,8 +290,10 @@
hss = HandleSignalsState();
EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
d0->AddWaiter(&w, MOJO_HANDLE_SIGNAL_READABLE, 2, &hss));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfied_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfiable_signals);
// Read again from |d0|.
buffer[0] = 0;
@@ -293,16 +310,16 @@
hss = HandleSignalsState();
EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
d0->AddWaiter(&w, MOJO_HANDLE_SIGNAL_READABLE, 3, &hss));
- EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(0u, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals);
// Try waiting for writable on |d0|; should fail (unsatisfiable).
w.Init();
hss = HandleSignalsState();
EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
d0->AddWaiter(&w, MOJO_HANDLE_SIGNAL_WRITABLE, 4, &hss));
- EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(0u, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals);
// Try reading from |d0|; should fail (nothing to read and other end
// closed).
@@ -374,8 +391,7 @@
EXPECT_EQ(1u, context);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
// Now |d1| is already readable. Try waiting for it again.
{
@@ -390,8 +406,7 @@
EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, result);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
// Consume what we wrote to |d0|.
buffer[0] = 0;
@@ -420,8 +435,8 @@
EXPECT_TRUE(did_wait);
EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result);
EXPECT_EQ(3u, context);
- EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(0u, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals);
EXPECT_EQ(MOJO_RESULT_OK, d1->Close());
}
diff --git a/mojo/edk/system/message_pipe_unittest.cc b/mojo/edk/system/message_pipe_unittest.cc
index 030084b..c700891 100644
--- a/mojo/edk/system/message_pipe_unittest.cc
+++ b/mojo/edk/system/message_pipe_unittest.cc
@@ -15,6 +15,10 @@
namespace system {
namespace {
+const MojoHandleSignals kAllSignals = MOJO_HANDLE_SIGNAL_READABLE |
+ MOJO_HANDLE_SIGNAL_WRITABLE |
+ MOJO_HANDLE_SIGNAL_PEER_CLOSED;
+
// Tests:
// - only default flags
// - reading messages from a port
@@ -335,8 +339,7 @@
EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
mp->AddWaiter(0, &waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 0, &hss));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
waiter.Init();
hss = HandleSignalsState();
EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
@@ -344,8 +347,7 @@
MOJO_HANDLE_SIGNAL_WRITABLE,
0, &hss));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
// Not yet readable.
waiter.Init();
@@ -355,8 +357,18 @@
hss = HandleSignalsState();
mp->RemoveWaiter(0, &waiter, &hss);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
+
+ // The peer is not closed.
+ waiter.Init();
+ ASSERT_EQ(
+ MOJO_RESULT_OK,
+ mp->AddWaiter(0, &waiter, MOJO_HANDLE_SIGNAL_PEER_CLOSED, 2, nullptr));
+ EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0, nullptr));
+ hss = HandleSignalsState();
+ mp->RemoveWaiter(0, &waiter, &hss);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
// Write from port 0 (to port 1), to make port 1 readable.
buffer[0] = 123456789;
@@ -368,11 +380,10 @@
waiter.Init();
hss = HandleSignalsState();
EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
- mp->AddWaiter(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 2, &hss));
+ mp->AddWaiter(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 3, &hss));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
waiter.Init();
hss = HandleSignalsState();
EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
@@ -381,36 +392,48 @@
0, &hss));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
// ... and still writable.
waiter.Init();
hss = HandleSignalsState();
EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
- mp->AddWaiter(1, &waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 3, &hss));
+ mp->AddWaiter(1, &waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 4, &hss));
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
// Close port 0.
mp->Close(0);
- // Now port 1 should not be writable.
+ // Port 1 should be signaled with peer closed.
+ waiter.Init();
+ hss = HandleSignalsState();
+ EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
+ mp->AddWaiter(1, &waiter, MOJO_HANDLE_SIGNAL_PEER_CLOSED, 5, &hss));
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfied_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfiable_signals);
+
+ // Port 1 should not be writable.
waiter.Init();
hss = HandleSignalsState();
EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
- mp->AddWaiter(1, &waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 4, &hss));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
+ mp->AddWaiter(1, &waiter, MOJO_HANDLE_SIGNAL_WRITABLE, 6, &hss));
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfied_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfiable_signals);
// But it should still be readable.
waiter.Init();
hss = HandleSignalsState();
EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS,
- mp->AddWaiter(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 5, &hss));
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
+ mp->AddWaiter(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 7, &hss));
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfied_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfiable_signals);
// Read from port 1.
buffer[0] = 0;
@@ -425,7 +448,7 @@
waiter.Init();
hss = HandleSignalsState();
EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
- mp->AddWaiter(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 6, nullptr));
+ mp->AddWaiter(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 8, nullptr));
EXPECT_EQ(0u, hss.satisfied_signals);
EXPECT_EQ(0u, hss.satisfiable_signals);
@@ -460,8 +483,7 @@
mp->RemoveWaiter(1, thread.waiter(), &hss);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
mp->Close(0);
mp->Close(1);
@@ -493,6 +515,29 @@
EXPECT_EQ(MOJO_RESULT_CANCELLED, result);
EXPECT_EQ(2u, context);
+ // Close to cancel waiter using peer closed signal.
+ {
+ scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalLocal());
+ test::SimpleWaiterThread thread(&result, &context);
+
+ thread.waiter()->Init();
+ ASSERT_EQ(MOJO_RESULT_OK,
+ mp->AddWaiter(1, thread.waiter(), MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ 3, nullptr));
+ thread.Start();
+
+ // Close port 1 first -- this should result in the waiter being cancelled.
+ mp->CancelAllWaiters(1);
+ mp->Close(1);
+
+ // Port 1 is closed, so |Dispatcher::RemoveWaiter()| wouldn't call into the
+ // |MessagePipe| to remove any waiter.
+
+ mp->Close(0);
+ } // Joins |thread|.
+ EXPECT_EQ(MOJO_RESULT_CANCELLED, result);
+ EXPECT_EQ(3u, context);
+
// Close to make waiter un-wake-up-able.
{
scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalLocal());
@@ -500,7 +545,7 @@
thread.waiter()->Init();
ASSERT_EQ(MOJO_RESULT_OK,
- mp->AddWaiter(1, thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 3,
+ mp->AddWaiter(1, thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 4,
nullptr));
thread.Start();
@@ -511,14 +556,14 @@
HandleSignalsState hss;
mp->RemoveWaiter(1, thread.waiter(), &hss);
- EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(0u, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals);
mp->CancelAllWaiters(1);
mp->Close(1);
} // Joins |thread|.
EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result);
- EXPECT_EQ(3u, context);
+ EXPECT_EQ(4u, context);
}
} // namespace
diff --git a/mojo/edk/system/multiprocess_message_pipe_unittest.cc b/mojo/edk/system/multiprocess_message_pipe_unittest.cc
index 37e777e..f486152 100644
--- a/mojo/edk/system/multiprocess_message_pipe_unittest.cc
+++ b/mojo/edk/system/multiprocess_message_pipe_unittest.cc
@@ -62,8 +62,8 @@
if (result != MOJO_RESULT_OK) {
// It was closed, probably.
CHECK_EQ(result, MOJO_RESULT_FAILED_PRECONDITION);
- CHECK_EQ(hss.satisfied_signals, 0u);
- CHECK_EQ(hss.satisfiable_signals, 0u);
+ CHECK_EQ(hss.satisfied_signals, MOJO_HANDLE_SIGNAL_PEER_CLOSED);
+ CHECK_EQ(hss.satisfiable_signals, MOJO_HANDLE_SIGNAL_PEER_CLOSED);
break;
} else {
CHECK((hss.satisfied_signals & MOJO_HANDLE_SIGNAL_READABLE));
@@ -196,8 +196,8 @@
HandleSignalsState hss;
EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
test::WaitIfNecessary(mp, MOJO_HANDLE_SIGNAL_READABLE, &hss));
- EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(0u, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals);
mp->Close(0);
@@ -223,8 +223,9 @@
// pipe before we do.
CHECK_EQ(hss.satisfied_signals,
MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE);
- CHECK_EQ(hss.satisfiable_signals,
- MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE);
+ CHECK_EQ(hss.satisfiable_signals, MOJO_HANDLE_SIGNAL_READABLE |
+ MOJO_HANDLE_SIGNAL_WRITABLE |
+ MOJO_HANDLE_SIGNAL_PEER_CLOSED);
// It should have a shared buffer.
std::string read_buffer(100, '\0');
@@ -272,8 +273,9 @@
MOJO_RESULT_OK);
CHECK_EQ(hss.satisfied_signals,
MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE);
- CHECK_EQ(hss.satisfiable_signals,
- MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE);
+ CHECK_EQ(hss.satisfiable_signals, MOJO_HANDLE_SIGNAL_READABLE |
+ MOJO_HANDLE_SIGNAL_WRITABLE |
+ MOJO_HANDLE_SIGNAL_PEER_CLOSED);
read_buffer = std::string(100, '\0');
num_bytes = static_cast<uint32_t>(read_buffer.size());
@@ -377,8 +379,8 @@
hss = HandleSignalsState();
EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
test::WaitIfNecessary(mp, MOJO_HANDLE_SIGNAL_READABLE, &hss));
- EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(0u, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals);
mp->Close(0);
@@ -400,8 +402,9 @@
MOJO_RESULT_OK);
CHECK_EQ(hss.satisfied_signals,
MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE);
- CHECK_EQ(hss.satisfiable_signals,
- MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE);
+ CHECK_EQ(hss.satisfiable_signals, MOJO_HANDLE_SIGNAL_READABLE |
+ MOJO_HANDLE_SIGNAL_WRITABLE |
+ MOJO_HANDLE_SIGNAL_PEER_CLOSED);
std::string read_buffer(100, '\0');
uint32_t num_bytes = static_cast<uint32_t>(read_buffer.size());
@@ -485,8 +488,8 @@
HandleSignalsState hss;
EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION,
test::WaitIfNecessary(mp, MOJO_HANDLE_SIGNAL_READABLE, &hss));
- EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(0u, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals);
mp->Close(0);
diff --git a/mojo/edk/system/remote_message_pipe_unittest.cc b/mojo/edk/system/remote_message_pipe_unittest.cc
index e3a320e..926ca0b 100644
--- a/mojo/edk/system/remote_message_pipe_unittest.cc
+++ b/mojo/edk/system/remote_message_pipe_unittest.cc
@@ -41,6 +41,10 @@
namespace system {
namespace {
+const MojoHandleSignals kAllSignals = MOJO_HANDLE_SIGNAL_READABLE |
+ MOJO_HANDLE_SIGNAL_WRITABLE |
+ MOJO_HANDLE_SIGNAL_PEER_CLOSED;
+
class RemoteMessagePipeTest : public testing::Test {
public:
RemoteMessagePipeTest() : io_thread_(base::TestIOThread::kAutoStart) {}
@@ -204,8 +208,7 @@
mp1->RemoveWaiter(1, &waiter, &hss);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
// Read from MP 1, port 1.
EXPECT_EQ(MOJO_RESULT_OK,
@@ -233,8 +236,7 @@
mp0->RemoveWaiter(0, &waiter, &hss);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
buffer_size = static_cast<uint32_t>(sizeof(buffer));
EXPECT_EQ(MOJO_RESULT_OK,
@@ -261,8 +263,44 @@
hss = HandleSignalsState();
mp1->RemoveWaiter(1, &waiter, &hss);
}
- EXPECT_EQ(0u, hss.satisfied_signals);
- EXPECT_EQ(0u, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals);
+
+ // And MP 1, port 1.
+ mp1->Close(1);
+}
+
+TEST_F(RemoteMessagePipeTest, PeerClosed) {
+ Waiter waiter;
+ HandleSignalsState hss;
+ uint32_t context = 0;
+
+ // Connect message pipes. MP 0, port 1 will be attached to channel 0 and
+ // connected to MP 1, port 0, which will be attached to channel 1. This leaves
+ // MP 0, port 0 and MP 1, port 1 as the "user-facing" endpoints.
+
+ scoped_refptr<ChannelEndpoint> ep0;
+ scoped_refptr<MessagePipe> mp0(MessagePipe::CreateLocalProxy(&ep0));
+ scoped_refptr<ChannelEndpoint> ep1;
+ scoped_refptr<MessagePipe> mp1(MessagePipe::CreateProxyLocal(&ep1));
+ BootstrapChannelEndpoints(ep0, ep1);
+
+ // Close MP 0, port 0.
+ mp0->Close(0);
+
+ // Try to wait for MP 1, port 1 to be signaled with peer closed.
+ waiter.Init();
+ hss = HandleSignalsState();
+ MojoResult result =
+ mp1->AddWaiter(1, &waiter, MOJO_HANDLE_SIGNAL_PEER_CLOSED, 101, &hss);
+ if (result == MOJO_RESULT_OK) {
+ EXPECT_EQ(MOJO_RESULT_OK, waiter.Wait(MOJO_DEADLINE_INDEFINITE, &context));
+ EXPECT_EQ(101u, context);
+ hss = HandleSignalsState();
+ mp1->RemoveWaiter(1, &waiter, &hss);
+ }
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals);
// And MP 1, port 1.
mp1->Close(1);
@@ -314,8 +352,7 @@
mp1->RemoveWaiter(1, &waiter, &hss);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
ChannelEndpointId received_id;
buffer_size = static_cast<uint32_t>(sizeof(received_id));
@@ -349,8 +386,7 @@
mp3->RemoveWaiter(0, &waiter, &hss);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
// Make sure there's nothing on MP 0, port 0 or MP 1, port 1 or MP 2, port 0.
buffer_size = static_cast<uint32_t>(sizeof(buffer));
@@ -396,7 +432,7 @@
mp1->RemoveWaiter(1, &waiter, &hss);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
+ EXPECT_EQ(kAllSignals | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
hss.satisfiable_signals);
// Make sure there's nothing on the other ports.
@@ -606,8 +642,7 @@
mp1->RemoveWaiter(1, &waiter, &hss);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
// Read from MP 1, port 1.
char read_buffer[100] = {0};
@@ -651,8 +686,7 @@
dispatcher->RemoveWaiter(&waiter, &hss);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
// Read from the dispatcher.
memset(read_buffer, 0, sizeof(read_buffer));
@@ -682,8 +716,7 @@
local_mp->RemoveWaiter(1, &waiter, &hss);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
// Read from "local_mp", port 1.
memset(read_buffer, 0, sizeof(read_buffer));
@@ -721,8 +754,7 @@
hss = local_mp->GetHandleSignalsState(0);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
// Write to the other end (|local_mp|, port 1), and then close it.
EXPECT_EQ(
MOJO_RESULT_OK,
@@ -731,8 +763,7 @@
hss = local_mp->GetHandleSignalsState(0);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
// Then the second message....
EXPECT_EQ(
MOJO_RESULT_OK,
@@ -741,8 +772,7 @@
hss = local_mp->GetHandleSignalsState(0);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
// Then close it.
local_mp->Close(1);
@@ -786,8 +816,7 @@
mp1->RemoveWaiter(1, &waiter, &hss);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
// Read from MP 1, port 1.
char read_buffer[100] = {0};
@@ -811,8 +840,10 @@
// |dispatcher| should already be readable and not writable.
hss = dispatcher->GetHandleSignalsState();
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfied_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfiable_signals);
// So read from it.
memset(read_buffer, 0, sizeof(read_buffer));
read_buffer_size = static_cast<uint32_t>(sizeof(read_buffer));
@@ -824,8 +855,10 @@
EXPECT_STREQ(kHello, read_buffer);
// It should still be readable.
hss = dispatcher->GetHandleSignalsState();
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfied_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ hss.satisfiable_signals);
// So read from it.
memset(read_buffer, 0, sizeof(read_buffer));
read_buffer_size = static_cast<uint32_t>(sizeof(read_buffer));
@@ -837,8 +870,8 @@
EXPECT_STREQ(kWorld, read_buffer);
// Now it should no longer be readable.
hss = dispatcher->GetHandleSignalsState();
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_NONE, hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_NONE, hss.satisfiable_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfied_signals);
+ EXPECT_EQ(MOJO_HANDLE_SIGNAL_PEER_CLOSED, hss.satisfiable_signals);
// Close everything that belongs to us.
mp0->Close(0);
@@ -917,8 +950,7 @@
mp1->RemoveWaiter(1, &waiter, &hss);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
// Read from MP 1, port 1.
char read_buffer[100] = {0};
@@ -1037,8 +1069,7 @@
mp1->RemoveWaiter(1, &waiter, &hss);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
// Read from MP 1, port 1.
char read_buffer[100] = {0};
@@ -1175,8 +1206,7 @@
mp1->RemoveWaiter(1, &waiter, &hss);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
// Read from MP 1, port 1.
char read_buffer[100] = {0};
@@ -1235,8 +1265,7 @@
mp0->RemoveWaiter(0, &waiter, &hss);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
// Read from MP 0, port 0.
read_buffer_size = static_cast<uint32_t>(sizeof(read_buffer));
@@ -1276,8 +1305,7 @@
dispatcher->RemoveWaiter(&waiter, &hss);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
// Read from the dispatcher.
memset(read_buffer, 0, sizeof(read_buffer));
@@ -1307,8 +1335,7 @@
local_mp->RemoveWaiter(1, &waiter, &hss);
EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
hss.satisfied_signals);
- EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE,
- hss.satisfiable_signals);
+ EXPECT_EQ(kAllSignals, hss.satisfiable_signals);
// Read from "local_mp", port 1.
memset(read_buffer, 0, sizeof(read_buffer));