OLD | NEW |
1 // Copyright 2014 The Crashpad Authors. All rights reserved. | 1 // Copyright 2014 The Crashpad Authors. All rights reserved. |
2 // | 2 // |
3 // Licensed under the Apache License, Version 2.0 (the "License"); | 3 // Licensed under the Apache License, Version 2.0 (the "License"); |
4 // you may not use this file except in compliance with the License. | 4 // you may not use this file except in compliance with the License. |
5 // You may obtain a copy of the License at | 5 // You may obtain a copy of the License at |
6 // | 6 // |
7 // http://www.apache.org/licenses/LICENSE-2.0 | 7 // http://www.apache.org/licenses/LICENSE-2.0 |
8 // | 8 // |
9 // Unless required by applicable law or agreed to in writing, software | 9 // Unless required by applicable law or agreed to in writing, software |
10 // distributed under the License is distributed on an "AS IS" BASIS, | 10 // distributed under the License is distributed on an "AS IS" BASIS, |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
58 parent_wait_for_child_pipe(false), | 58 parent_wait_for_child_pipe(false), |
59 server_options(MACH_MSG_OPTION_NONE), | 59 server_options(MACH_MSG_OPTION_NONE), |
60 server_persistent(MachMessageServer::kOneShot), | 60 server_persistent(MachMessageServer::kOneShot), |
61 server_nonblocking(MachMessageServer::kBlocking), | 61 server_nonblocking(MachMessageServer::kBlocking), |
62 server_timeout_ms(MACH_MSG_TIMEOUT_NONE), | 62 server_timeout_ms(MACH_MSG_TIMEOUT_NONE), |
63 server_mig_retcode(KERN_SUCCESS), | 63 server_mig_retcode(KERN_SUCCESS), |
64 server_destroy_complex(true), | 64 server_destroy_complex(true), |
65 expect_server_destroyed_complex(true), | 65 expect_server_destroyed_complex(true), |
66 expect_server_result(KERN_SUCCESS), | 66 expect_server_result(KERN_SUCCESS), |
67 expect_server_transaction_count(1), | 67 expect_server_transaction_count(1), |
| 68 child_wait_for_parent_pipe_early(false), |
68 client_send_request_count(1), | 69 client_send_request_count(1), |
69 client_send_complex(false), | 70 client_send_complex(false), |
70 client_send_large(false), | 71 client_send_large(false), |
71 client_reply_port_type(kReplyPortNormal), | 72 client_reply_port_type(kReplyPortNormal), |
72 client_expect_reply(true), | 73 client_expect_reply(true), |
73 child_send_all_requests_before_receiving_any_replies(false), | 74 child_send_all_requests_before_receiving_any_replies(false), |
74 child_wait_for_parent_pipe(false) { | 75 child_wait_for_parent_pipe_late(false) { |
75 } | 76 } |
76 | 77 |
77 // true if MachMessageServerFunction() is expected to be called. | 78 // true if MachMessageServerFunction() is expected to be called. |
78 bool expect_server_interface_method_called; | 79 bool expect_server_interface_method_called; |
79 | 80 |
80 // true if the parent should wait for the child to write a byte to the pipe | 81 // true if the parent should wait for the child to write a byte to the pipe |
81 // as a signal that the child is ready for the parent to begin its side of | 82 // as a signal that the child is ready for the parent to begin its side of |
82 // the test. This is used for nonblocking tests, which require that there | 83 // the test. This is used for nonblocking tests, which require that there |
83 // be something in the server’s queue before attempting a nonblocking | 84 // be something in the server’s queue before attempting a nonblocking |
84 // receive if the receive is to be successful. | 85 // receive if the receive is to be successful. |
(...skipping 26 matching lines...) Expand all Loading... |
111 // server_destroy_complex is false, a complex message will be destroyed if | 112 // server_destroy_complex is false, a complex message will be destroyed if |
112 // the MIG return code was unsuccessful. | 113 // the MIG return code was unsuccessful. |
113 bool expect_server_destroyed_complex; | 114 bool expect_server_destroyed_complex; |
114 | 115 |
115 // The expected return value from MachMessageServer::Run(). | 116 // The expected return value from MachMessageServer::Run(). |
116 kern_return_t expect_server_result; | 117 kern_return_t expect_server_result; |
117 | 118 |
118 // The number of transactions that the server is expected to handle. | 119 // The number of transactions that the server is expected to handle. |
119 size_t expect_server_transaction_count; | 120 size_t expect_server_transaction_count; |
120 | 121 |
| 122 // true if the child should wait for the parent to signal that it’s ready |
| 123 // for the child to begin sending requests via the pipe. This is done if the |
| 124 // parent needs to perform operations on its receive port before the child |
| 125 // should be permitted to send anything to it. Currently, this is used to |
| 126 // allow the parent to ensure that the receive port’s queue length is high |
| 127 // enough before the child begins attempting to fill it. |
| 128 bool child_wait_for_parent_pipe_early; |
| 129 |
121 // The number of requests that the client should send to the server. | 130 // The number of requests that the client should send to the server. |
122 size_t client_send_request_count; | 131 size_t client_send_request_count; |
123 | 132 |
124 // true if the client should send a complex message, one that carries a port | 133 // true if the client should send a complex message, one that carries a port |
125 // descriptor in its body. Normally false. | 134 // descriptor in its body. Normally false. |
126 bool client_send_complex; | 135 bool client_send_complex; |
127 | 136 |
128 // true if the client should send a larger message than the server has | 137 // true if the client should send a larger message than the server has |
129 // allocated space to receive. If server_options contains MACH_RCV_LARGE, | 138 // allocated space to receive. If server_options contains MACH_RCV_LARGE, |
130 // the server will resize its buffer to receive the message. Otherwise, the | 139 // the server will resize its buffer to receive the message. Otherwise, the |
(...skipping 17 matching lines...) Expand all Loading... |
148 // test, which requires the client to fill the server’s queue before the | 157 // test, which requires the client to fill the server’s queue before the |
149 // server can attempt processing it. | 158 // server can attempt processing it. |
150 bool child_send_all_requests_before_receiving_any_replies; | 159 bool child_send_all_requests_before_receiving_any_replies; |
151 | 160 |
152 // true if the child should wait to receive a byte from the parent before | 161 // true if the child should wait to receive a byte from the parent before |
153 // exiting. This can be used to keep a receive right in the child alive | 162 // exiting. This can be used to keep a receive right in the child alive |
154 // until the parent has a chance to verify that it’s holding a send right. | 163 // until the parent has a chance to verify that it’s holding a send right. |
155 // Otherwise, the right might appear in the parent as a dead name if the | 164 // Otherwise, the right might appear in the parent as a dead name if the |
156 // child exited before the parent had a chance to examine it. This would be | 165 // child exited before the parent had a chance to examine it. This would be |
157 // a race. | 166 // a race. |
158 bool child_wait_for_parent_pipe; | 167 bool child_wait_for_parent_pipe_late; |
159 }; | 168 }; |
160 | 169 |
161 explicit TestMachMessageServer(const Options& options) | 170 explicit TestMachMessageServer(const Options& options) |
162 : MachMessageServer::Interface(), | 171 : MachMessageServer::Interface(), |
163 MachMultiprocess(), | 172 MachMultiprocess(), |
164 options_(options), | 173 options_(options), |
165 child_complex_message_port_(), | 174 child_complex_message_port_(), |
166 parent_complex_message_port_(MACH_PORT_NULL) { | 175 parent_complex_message_port_(MACH_PORT_NULL) { |
167 } | 176 } |
168 | 177 |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
290 uint8_t data[4 * PAGE_SIZE]; | 299 uint8_t data[4 * PAGE_SIZE]; |
291 }; | 300 }; |
292 | 301 |
293 struct ReplyMessage : public mig_reply_error_t { | 302 struct ReplyMessage : public mig_reply_error_t { |
294 uint32_t number; | 303 uint32_t number; |
295 }; | 304 }; |
296 | 305 |
297 // MachMultiprocess: | 306 // MachMultiprocess: |
298 | 307 |
299 virtual void MachMultiprocessParent() override { | 308 virtual void MachMultiprocessParent() override { |
| 309 mach_port_t local_port = LocalPort(); |
| 310 |
| 311 kern_return_t kr; |
| 312 if (options_.child_send_all_requests_before_receiving_any_replies) { |
| 313 // On Mac OS X 10.10, the queue limit of a new Mach port seems to be 2 |
| 314 // by default, which is below the value of MACH_PORT_QLIMIT_DEFAULT. Set |
| 315 // the port’s queue limit explicitly here. |
| 316 mach_port_limits limits = {}; |
| 317 limits.mpl_qlimit = MACH_PORT_QLIMIT_DEFAULT; |
| 318 kr = mach_port_set_attributes(mach_task_self(), |
| 319 local_port, |
| 320 MACH_PORT_LIMITS_INFO, |
| 321 reinterpret_cast<mach_port_info_t>(&limits), |
| 322 MACH_PORT_LIMITS_INFO_COUNT); |
| 323 ASSERT_EQ(KERN_SUCCESS, kr) |
| 324 << MachErrorMessage(kr, "mach_port_set_attributes"); |
| 325 } |
| 326 |
| 327 if (options_.child_wait_for_parent_pipe_early) { |
| 328 // Tell the child to begin sending messages. |
| 329 char c = '\0'; |
| 330 CheckedWriteFD(WritePipeFD(), &c, 1); |
| 331 } |
| 332 |
300 if (options_.parent_wait_for_child_pipe) { | 333 if (options_.parent_wait_for_child_pipe) { |
301 // Wait until the child is done sending what it’s going to send. | 334 // Wait until the child is done sending what it’s going to send. |
302 char c; | 335 char c; |
303 CheckedReadFD(ReadPipeFD(), &c, 1); | 336 CheckedReadFD(ReadPipeFD(), &c, 1); |
304 EXPECT_EQ('\0', c); | 337 EXPECT_EQ('\0', c); |
305 } | 338 } |
306 | 339 |
307 kern_return_t kr; | |
308 ASSERT_EQ(options_.expect_server_result, | 340 ASSERT_EQ(options_.expect_server_result, |
309 (kr = MachMessageServer::Run(this, | 341 (kr = MachMessageServer::Run(this, |
310 LocalPort(), | 342 local_port, |
311 options_.server_options, | 343 options_.server_options, |
312 options_.server_persistent, | 344 options_.server_persistent, |
313 options_.server_nonblocking, | 345 options_.server_nonblocking, |
314 options_.server_timeout_ms))) | 346 options_.server_timeout_ms))) |
315 << MachErrorMessage(kr, "MachMessageServer"); | 347 << MachErrorMessage(kr, "MachMessageServer"); |
316 | 348 |
317 if (options_.client_send_complex) { | 349 if (options_.client_send_complex) { |
318 EXPECT_NE(kMachPortNull, parent_complex_message_port_); | 350 EXPECT_NE(kMachPortNull, parent_complex_message_port_); |
319 mach_port_type_t type; | 351 mach_port_type_t type; |
320 | 352 |
(...skipping 15 matching lines...) Expand all Loading... |
336 // The kernel won’t have reused the same name for another Mach port in | 368 // The kernel won’t have reused the same name for another Mach port in |
337 // this task so soon. It’s possible that something else in this task could | 369 // this task so soon. It’s possible that something else in this task could |
338 // have reused the name, but it’s unlikely for that to have happened in | 370 // have reused the name, but it’s unlikely for that to have happened in |
339 // this test environment. | 371 // this test environment. |
340 kr = mach_port_type( | 372 kr = mach_port_type( |
341 mach_task_self(), parent_complex_message_port_, &type); | 373 mach_task_self(), parent_complex_message_port_, &type); |
342 EXPECT_EQ(KERN_INVALID_NAME, kr) | 374 EXPECT_EQ(KERN_INVALID_NAME, kr) |
343 << MachErrorMessage(kr, "mach_port_type"); | 375 << MachErrorMessage(kr, "mach_port_type"); |
344 } | 376 } |
345 | 377 |
346 if (options_.child_wait_for_parent_pipe) { | 378 if (options_.child_wait_for_parent_pipe_late) { |
347 // Let the child know it’s safe to exit. | 379 // Let the child know it’s safe to exit. |
348 char c = '\0'; | 380 char c = '\0'; |
349 CheckedWriteFD(WritePipeFD(), &c, 1); | 381 CheckedWriteFD(WritePipeFD(), &c, 1); |
350 } | 382 } |
351 } | 383 } |
352 | 384 |
353 virtual void MachMultiprocessChild() override { | 385 virtual void MachMultiprocessChild() override { |
| 386 if (options_.child_wait_for_parent_pipe_early) { |
| 387 // Wait until the parent is done setting things up on its end. |
| 388 char c; |
| 389 CheckedReadFD(ReadPipeFD(), &c, 1); |
| 390 EXPECT_EQ('\0', c); |
| 391 } |
| 392 |
354 for (size_t index = 0; | 393 for (size_t index = 0; |
355 index < options_.client_send_request_count; | 394 index < options_.client_send_request_count; |
356 ++index) { | 395 ++index) { |
357 if (options_.child_send_all_requests_before_receiving_any_replies) { | 396 if (options_.child_send_all_requests_before_receiving_any_replies) { |
358 // For this test, all of the messages need to go into the queue before | 397 // For this test, all of the messages need to go into the queue before |
359 // the parent is allowed to start processing them. Don’t attempt to | 398 // the parent is allowed to start processing them. Don’t attempt to |
360 // process replies before all of the requests are sent, because the | 399 // process replies before all of the requests are sent, because the |
361 // server won’t have sent any replies until all of the requests are in | 400 // server won’t have sent any replies until all of the requests are in |
362 // its queue. | 401 // its queue. |
363 ChildSendRequest(); | 402 ChildSendRequest(); |
(...skipping 17 matching lines...) Expand all Loading... |
381 for (size_t index = 0; | 420 for (size_t index = 0; |
382 index < options_.client_send_request_count; | 421 index < options_.client_send_request_count; |
383 ++index) { | 422 ++index) { |
384 ChildWaitForReply(); | 423 ChildWaitForReply(); |
385 if (testing::Test::HasFatalFailure()) { | 424 if (testing::Test::HasFatalFailure()) { |
386 return; | 425 return; |
387 } | 426 } |
388 } | 427 } |
389 } | 428 } |
390 | 429 |
391 if (options_.child_wait_for_parent_pipe) { | 430 if (options_.child_wait_for_parent_pipe_late) { |
392 char c; | 431 char c; |
393 CheckedReadFD(ReadPipeFD(), &c, 1); | 432 CheckedReadFD(ReadPipeFD(), &c, 1); |
394 ASSERT_EQ('\0', c); | 433 ASSERT_EQ('\0', c); |
395 } | 434 } |
396 } | 435 } |
397 | 436 |
398 // In the child process, sends a request message to the server. | 437 // In the child process, sends a request message to the server. |
399 void ChildSendRequest() { | 438 void ChildSendRequest() { |
400 // local_receive_port_owner will the receive right that is created in this | 439 // local_receive_port_owner will the receive right that is created in this |
401 // scope and intended to be destroyed when leaving this scope, after it has | 440 // scope and intended to be destroyed when leaving this scope, after it has |
(...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
642 // that it’s safe to start waiting for them in nonblocking mode. The server | 681 // that it’s safe to start waiting for them in nonblocking mode. The server |
643 // then listens for them in nonblocking persistent mode, and receives all of | 682 // then listens for them in nonblocking persistent mode, and receives all of |
644 // them because they’ve been queued up. The client doesn’t wait for the | 683 // them because they’ve been queued up. The client doesn’t wait for the |
645 // replies until after it’s put all of its requests into the server’s queue. | 684 // replies until after it’s put all of its requests into the server’s queue. |
646 // | 685 // |
647 // This test is sensitive to the length of the IPC queue limit. Mach ports | 686 // This test is sensitive to the length of the IPC queue limit. Mach ports |
648 // normally have a queue length limit of MACH_PORT_QLIMIT_DEFAULT (which is | 687 // normally have a queue length limit of MACH_PORT_QLIMIT_DEFAULT (which is |
649 // MACH_PORT_QLIMIT_BASIC, or 5). The number of messages sent for this test | 688 // MACH_PORT_QLIMIT_BASIC, or 5). The number of messages sent for this test |
650 // must be below this, because the server does not begin dequeueing request | 689 // must be below this, because the server does not begin dequeueing request |
651 // messages until the client has finished sending them. | 690 // messages until the client has finished sending them. |
| 691 // |
| 692 // The queue limit on new ports has been seen to be below |
| 693 // MACH_PORT_QLIMIT_DEFAULT, so it will explicitly be set by |
| 694 // mach_port_set_attributes() for this test. This needs to happen before the |
| 695 // child is allowed to begin sending messages, so |
| 696 // child_wait_for_parent_pipe_early is used to make the child wait until the |
| 697 // parent is ready. |
652 const size_t kTransactionCount = 4; | 698 const size_t kTransactionCount = 4; |
653 COMPILE_ASSERT(kTransactionCount <= MACH_PORT_QLIMIT_DEFAULT, | 699 COMPILE_ASSERT(kTransactionCount <= MACH_PORT_QLIMIT_DEFAULT, |
654 must_not_exceed_queue_limit); | 700 must_not_exceed_queue_limit); |
655 | 701 |
656 TestMachMessageServer::Options options; | 702 TestMachMessageServer::Options options; |
657 options.parent_wait_for_child_pipe = true; | 703 options.parent_wait_for_child_pipe = true; |
658 options.server_persistent = MachMessageServer::kPersistent; | 704 options.server_persistent = MachMessageServer::kPersistent; |
659 options.server_nonblocking = MachMessageServer::kNonblocking; | 705 options.server_nonblocking = MachMessageServer::kNonblocking; |
660 options.expect_server_result = MACH_RCV_TIMED_OUT; | 706 options.expect_server_result = MACH_RCV_TIMED_OUT; |
661 options.expect_server_transaction_count = kTransactionCount; | 707 options.expect_server_transaction_count = kTransactionCount; |
| 708 options.child_wait_for_parent_pipe_early = true; |
662 options.client_send_request_count = kTransactionCount; | 709 options.client_send_request_count = kTransactionCount; |
663 options.child_send_all_requests_before_receiving_any_replies = true; | 710 options.child_send_all_requests_before_receiving_any_replies = true; |
664 TestMachMessageServer test_mach_message_server(options); | 711 TestMachMessageServer test_mach_message_server(options); |
665 test_mach_message_server.Test(); | 712 test_mach_message_server.Test(); |
666 } | 713 } |
667 | 714 |
668 TEST(MachMessageServer, ReturnCodeInvalidArgument) { | 715 TEST(MachMessageServer, ReturnCodeInvalidArgument) { |
669 // This tests that the mig_reply_error_t::RetCode field is properly returned | 716 // This tests that the mig_reply_error_t::RetCode field is properly returned |
670 // to the client. | 717 // to the client. |
671 TestMachMessageServer::Options options; | 718 TestMachMessageServer::Options options; |
672 options.server_mig_retcode = KERN_INVALID_ARGUMENT; | 719 options.server_mig_retcode = KERN_INVALID_ARGUMENT; |
673 TestMachMessageServer test_mach_message_server(options); | 720 TestMachMessageServer test_mach_message_server(options); |
674 test_mach_message_server.Test(); | 721 test_mach_message_server.Test(); |
675 } | 722 } |
676 | 723 |
677 TEST(MachMessageServer, ReturnCodeNoReply) { | 724 TEST(MachMessageServer, ReturnCodeNoReply) { |
678 // This tests that when mig_reply_error_t::RetCode is set to MIG_NO_REPLY, no | 725 // This tests that when mig_reply_error_t::RetCode is set to MIG_NO_REPLY, no |
679 // response is sent to the client. | 726 // response is sent to the client. |
680 TestMachMessageServer::Options options; | 727 TestMachMessageServer::Options options; |
681 options.server_mig_retcode = MIG_NO_REPLY; | 728 options.server_mig_retcode = MIG_NO_REPLY; |
682 options.client_expect_reply = false; | 729 options.client_expect_reply = false; |
683 options.child_wait_for_parent_pipe = true; | 730 options.child_wait_for_parent_pipe_late = true; |
684 TestMachMessageServer test_mach_message_server(options); | 731 TestMachMessageServer test_mach_message_server(options); |
685 test_mach_message_server.Test(); | 732 test_mach_message_server.Test(); |
686 } | 733 } |
687 | 734 |
688 TEST(MachMessageServer, ReplyPortNull) { | 735 TEST(MachMessageServer, ReplyPortNull) { |
689 // The client sets its reply port to MACH_PORT_NULL. The server should see | 736 // The client sets its reply port to MACH_PORT_NULL. The server should see |
690 // this and avoid sending a message to the null port. No reply message is | 737 // this and avoid sending a message to the null port. No reply message is |
691 // sent and the server returns success. | 738 // sent and the server returns success. |
692 TestMachMessageServer::Options options; | 739 TestMachMessageServer::Options options; |
693 options.client_reply_port_type = | 740 options.client_reply_port_type = |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
759 TEST(MachMessageServer, ComplexNotDestroyedNoReply) { | 806 TEST(MachMessageServer, ComplexNotDestroyedNoReply) { |
760 // As in MachMessageServer.ComplexNotDestroyed, but the server does not send | 807 // As in MachMessageServer.ComplexNotDestroyed, but the server does not send |
761 // a reply message and is expected to retain the send right in the server | 808 // a reply message and is expected to retain the send right in the server |
762 // task. | 809 // task. |
763 TestMachMessageServer::Options options; | 810 TestMachMessageServer::Options options; |
764 options.server_mig_retcode = MIG_NO_REPLY; | 811 options.server_mig_retcode = MIG_NO_REPLY; |
765 options.server_destroy_complex = false; | 812 options.server_destroy_complex = false; |
766 options.expect_server_destroyed_complex = false; | 813 options.expect_server_destroyed_complex = false; |
767 options.client_send_complex = true; | 814 options.client_send_complex = true; |
768 options.client_expect_reply = false; | 815 options.client_expect_reply = false; |
769 options.child_wait_for_parent_pipe = true; | 816 options.child_wait_for_parent_pipe_late = true; |
770 TestMachMessageServer test_mach_message_server(options); | 817 TestMachMessageServer test_mach_message_server(options); |
771 test_mach_message_server.Test(); | 818 test_mach_message_server.Test(); |
772 } | 819 } |
773 | 820 |
774 TEST(MachMessageServer, LargeUnexpected) { | 821 TEST(MachMessageServer, LargeUnexpected) { |
775 // The client sends a request to the server that is larger than the server is | 822 // The client sends a request to the server that is larger than the server is |
776 // expecting. The server did not specify MACH_RCV_LARGE in its options, so the | 823 // expecting. The server did not specify MACH_RCV_LARGE in its options, so the |
777 // request is destroyed and the server returns a MACH_RCV_TOO_LARGE error. The | 824 // request is destroyed and the server returns a MACH_RCV_TOO_LARGE error. The |
778 // client does not receive a reply. | 825 // client does not receive a reply. |
779 TestMachMessageServer::Options options; | 826 TestMachMessageServer::Options options; |
(...skipping 11 matching lines...) Expand all Loading... |
791 // so a new buffer is allocated to receive the message. The server receives | 838 // so a new buffer is allocated to receive the message. The server receives |
792 // the large request message, processes it, and returns a reply to the client. | 839 // the large request message, processes it, and returns a reply to the client. |
793 TestMachMessageServer::Options options; | 840 TestMachMessageServer::Options options; |
794 options.server_options = MACH_RCV_LARGE; | 841 options.server_options = MACH_RCV_LARGE; |
795 options.client_send_large = true; | 842 options.client_send_large = true; |
796 TestMachMessageServer test_mach_message_server(options); | 843 TestMachMessageServer test_mach_message_server(options); |
797 test_mach_message_server.Test(); | 844 test_mach_message_server.Test(); |
798 } | 845 } |
799 | 846 |
800 } // namespace | 847 } // namespace |
OLD | NEW |