mirror of
https://github.com/chromium/crashpad.git
synced 2025-03-09 14:06:33 +00:00
MachMessageServer test: deal with short receive queue lengths on 10.10.
The queue length of a new receive port appears to be 2 on Mac OS X 10.10 DP8 14A361c. The value of MACH_PORT_QLIMIT_DEFAULT in the 10.10 SDK is still 5, so a read of the kernel source should be interesting, if we ever get to see it. In the meantime, mach_port_set_attributes() can be used to set a traditional queue length. TEST=util_test MachMessageServer.PersistentNonblockingFourMessages R=rsesek@chromium.org Review URL: https://codereview.chromium.org/584293003
This commit is contained in:
parent
75988925f9
commit
8eec7874fd
@ -65,13 +65,14 @@ class TestMachMessageServer : public MachMessageServer::Interface,
|
||||
expect_server_destroyed_complex(true),
|
||||
expect_server_result(KERN_SUCCESS),
|
||||
expect_server_transaction_count(1),
|
||||
child_wait_for_parent_pipe_early(false),
|
||||
client_send_request_count(1),
|
||||
client_send_complex(false),
|
||||
client_send_large(false),
|
||||
client_reply_port_type(kReplyPortNormal),
|
||||
client_expect_reply(true),
|
||||
child_send_all_requests_before_receiving_any_replies(false),
|
||||
child_wait_for_parent_pipe(false) {
|
||||
child_wait_for_parent_pipe_late(false) {
|
||||
}
|
||||
|
||||
// true if MachMessageServerFunction() is expected to be called.
|
||||
@ -118,6 +119,14 @@ class TestMachMessageServer : public MachMessageServer::Interface,
|
||||
// The number of transactions that the server is expected to handle.
|
||||
size_t expect_server_transaction_count;
|
||||
|
||||
// true if the child should wait for the parent to signal that it’s ready
|
||||
// for the child to begin sending requests via the pipe. This is done if the
|
||||
// parent needs to perform operations on its receive port before the child
|
||||
// should be permitted to send anything to it. Currently, this is used to
|
||||
// allow the parent to ensure that the receive port’s queue length is high
|
||||
// enough before the child begins attempting to fill it.
|
||||
bool child_wait_for_parent_pipe_early;
|
||||
|
||||
// The number of requests that the client should send to the server.
|
||||
size_t client_send_request_count;
|
||||
|
||||
@ -155,7 +164,7 @@ class TestMachMessageServer : public MachMessageServer::Interface,
|
||||
// Otherwise, the right might appear in the parent as a dead name if the
|
||||
// child exited before the parent had a chance to examine it. This would be
|
||||
// a race.
|
||||
bool child_wait_for_parent_pipe;
|
||||
bool child_wait_for_parent_pipe_late;
|
||||
};
|
||||
|
||||
explicit TestMachMessageServer(const Options& options)
|
||||
@ -297,6 +306,30 @@ class TestMachMessageServer : public MachMessageServer::Interface,
|
||||
// MachMultiprocess:
|
||||
|
||||
virtual void MachMultiprocessParent() override {
|
||||
mach_port_t local_port = LocalPort();
|
||||
|
||||
kern_return_t kr;
|
||||
if (options_.child_send_all_requests_before_receiving_any_replies) {
|
||||
// On Mac OS X 10.10, the queue limit of a new Mach port seems to be 2
|
||||
// by default, which is below the value of MACH_PORT_QLIMIT_DEFAULT. Set
|
||||
// the port’s queue limit explicitly here.
|
||||
mach_port_limits limits = {};
|
||||
limits.mpl_qlimit = MACH_PORT_QLIMIT_DEFAULT;
|
||||
kr = mach_port_set_attributes(mach_task_self(),
|
||||
local_port,
|
||||
MACH_PORT_LIMITS_INFO,
|
||||
reinterpret_cast<mach_port_info_t>(&limits),
|
||||
MACH_PORT_LIMITS_INFO_COUNT);
|
||||
ASSERT_EQ(KERN_SUCCESS, kr)
|
||||
<< MachErrorMessage(kr, "mach_port_set_attributes");
|
||||
}
|
||||
|
||||
if (options_.child_wait_for_parent_pipe_early) {
|
||||
// Tell the child to begin sending messages.
|
||||
char c = '\0';
|
||||
CheckedWriteFD(WritePipeFD(), &c, 1);
|
||||
}
|
||||
|
||||
if (options_.parent_wait_for_child_pipe) {
|
||||
// Wait until the child is done sending what it’s going to send.
|
||||
char c;
|
||||
@ -304,10 +337,9 @@ class TestMachMessageServer : public MachMessageServer::Interface,
|
||||
EXPECT_EQ('\0', c);
|
||||
}
|
||||
|
||||
kern_return_t kr;
|
||||
ASSERT_EQ(options_.expect_server_result,
|
||||
(kr = MachMessageServer::Run(this,
|
||||
LocalPort(),
|
||||
local_port,
|
||||
options_.server_options,
|
||||
options_.server_persistent,
|
||||
options_.server_nonblocking,
|
||||
@ -343,7 +375,7 @@ class TestMachMessageServer : public MachMessageServer::Interface,
|
||||
<< MachErrorMessage(kr, "mach_port_type");
|
||||
}
|
||||
|
||||
if (options_.child_wait_for_parent_pipe) {
|
||||
if (options_.child_wait_for_parent_pipe_late) {
|
||||
// Let the child know it’s safe to exit.
|
||||
char c = '\0';
|
||||
CheckedWriteFD(WritePipeFD(), &c, 1);
|
||||
@ -351,6 +383,13 @@ class TestMachMessageServer : public MachMessageServer::Interface,
|
||||
}
|
||||
|
||||
virtual void MachMultiprocessChild() override {
|
||||
if (options_.child_wait_for_parent_pipe_early) {
|
||||
// Wait until the parent is done setting things up on its end.
|
||||
char c;
|
||||
CheckedReadFD(ReadPipeFD(), &c, 1);
|
||||
EXPECT_EQ('\0', c);
|
||||
}
|
||||
|
||||
for (size_t index = 0;
|
||||
index < options_.client_send_request_count;
|
||||
++index) {
|
||||
@ -388,7 +427,7 @@ class TestMachMessageServer : public MachMessageServer::Interface,
|
||||
}
|
||||
}
|
||||
|
||||
if (options_.child_wait_for_parent_pipe) {
|
||||
if (options_.child_wait_for_parent_pipe_late) {
|
||||
char c;
|
||||
CheckedReadFD(ReadPipeFD(), &c, 1);
|
||||
ASSERT_EQ('\0', c);
|
||||
@ -649,6 +688,13 @@ TEST(MachMessageServer, PersistentNonblockingFourMessages) {
|
||||
// MACH_PORT_QLIMIT_BASIC, or 5). The number of messages sent for this test
|
||||
// must be below this, because the server does not begin dequeueing request
|
||||
// messages until the client has finished sending them.
|
||||
//
|
||||
// The queue limit on new ports has been seen to be below
|
||||
// MACH_PORT_QLIMIT_DEFAULT, so it will explicitly be set by
|
||||
// mach_port_set_attributes() for this test. This needs to happen before the
|
||||
// child is allowed to begin sending messages, so
|
||||
// child_wait_for_parent_pipe_early is used to make the child wait until the
|
||||
// parent is ready.
|
||||
const size_t kTransactionCount = 4;
|
||||
COMPILE_ASSERT(kTransactionCount <= MACH_PORT_QLIMIT_DEFAULT,
|
||||
must_not_exceed_queue_limit);
|
||||
@ -659,6 +705,7 @@ TEST(MachMessageServer, PersistentNonblockingFourMessages) {
|
||||
options.server_nonblocking = MachMessageServer::kNonblocking;
|
||||
options.expect_server_result = MACH_RCV_TIMED_OUT;
|
||||
options.expect_server_transaction_count = kTransactionCount;
|
||||
options.child_wait_for_parent_pipe_early = true;
|
||||
options.client_send_request_count = kTransactionCount;
|
||||
options.child_send_all_requests_before_receiving_any_replies = true;
|
||||
TestMachMessageServer test_mach_message_server(options);
|
||||
@ -680,7 +727,7 @@ TEST(MachMessageServer, ReturnCodeNoReply) {
|
||||
TestMachMessageServer::Options options;
|
||||
options.server_mig_retcode = MIG_NO_REPLY;
|
||||
options.client_expect_reply = false;
|
||||
options.child_wait_for_parent_pipe = true;
|
||||
options.child_wait_for_parent_pipe_late = true;
|
||||
TestMachMessageServer test_mach_message_server(options);
|
||||
test_mach_message_server.Test();
|
||||
}
|
||||
@ -766,7 +813,7 @@ TEST(MachMessageServer, ComplexNotDestroyedNoReply) {
|
||||
options.expect_server_destroyed_complex = false;
|
||||
options.client_send_complex = true;
|
||||
options.client_expect_reply = false;
|
||||
options.child_wait_for_parent_pipe = true;
|
||||
options.child_wait_for_parent_pipe_late = true;
|
||||
TestMachMessageServer test_mach_message_server(options);
|
||||
test_mach_message_server.Test();
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user