| 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 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 60 } | 60 } |
| 61 | 61 |
| 62 const char kTestMemory[] = "Read me from another process"; | 62 const char kTestMemory[] = "Read me from another process"; |
| 63 | 63 |
| 64 class ProcessReaderChild final : public MachMultiprocess { | 64 class ProcessReaderChild final : public MachMultiprocess { |
| 65 public: | 65 public: |
| 66 ProcessReaderChild() : MachMultiprocess() {} | 66 ProcessReaderChild() : MachMultiprocess() {} |
| 67 | 67 |
| 68 ~ProcessReaderChild() {} | 68 ~ProcessReaderChild() {} |
| 69 | 69 |
| 70 protected: | 70 private: |
| 71 void Parent() override { | 71 void MachMultiprocessParent() override { |
| 72 ProcessReader process_reader; | 72 ProcessReader process_reader; |
| 73 ASSERT_TRUE(process_reader.Initialize(ChildTask())); | 73 ASSERT_TRUE(process_reader.Initialize(ChildTask())); |
| 74 | 74 |
| 75 #if !defined(ARCH_CPU_64_BITS) | 75 #if !defined(ARCH_CPU_64_BITS) |
| 76 EXPECT_FALSE(process_reader.Is64Bit()); | 76 EXPECT_FALSE(process_reader.Is64Bit()); |
| 77 #else | 77 #else |
| 78 EXPECT_TRUE(process_reader.Is64Bit()); | 78 EXPECT_TRUE(process_reader.Is64Bit()); |
| 79 #endif | 79 #endif |
| 80 | 80 |
| 81 EXPECT_EQ(getpid(), process_reader.ParentProcessID()); | 81 EXPECT_EQ(getpid(), process_reader.ParentProcessID()); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 93 EXPECT_EQ(kTestMemory, read_string); | 93 EXPECT_EQ(kTestMemory, read_string); |
| 94 | 94 |
| 95 // Tell the child that it’s OK to exit. The child needed to be kept alive | 95 // Tell the child that it’s OK to exit. The child needed to be kept alive |
| 96 // until the parent finished working with it. | 96 // until the parent finished working with it. |
| 97 int write_fd = WritePipeFD(); | 97 int write_fd = WritePipeFD(); |
| 98 char c = '\0'; | 98 char c = '\0'; |
| 99 rv = WriteFD(write_fd, &c, 1); | 99 rv = WriteFD(write_fd, &c, 1); |
| 100 ASSERT_EQ(1, rv) << ErrnoMessage("write"); | 100 ASSERT_EQ(1, rv) << ErrnoMessage("write"); |
| 101 } | 101 } |
| 102 | 102 |
| 103 void Child() override { | 103 void MachMultiprocessChild() override { |
| 104 int write_fd = WritePipeFD(); | 104 int write_fd = WritePipeFD(); |
| 105 | 105 |
| 106 mach_vm_address_t address = | 106 mach_vm_address_t address = |
| 107 reinterpret_cast<mach_vm_address_t>(kTestMemory); | 107 reinterpret_cast<mach_vm_address_t>(kTestMemory); |
| 108 int rv = WriteFD(write_fd, &address, sizeof(address)); | 108 int rv = WriteFD(write_fd, &address, sizeof(address)); |
| 109 ASSERT_EQ(static_cast<ssize_t>(sizeof(address)), rv) | 109 ASSERT_EQ(static_cast<ssize_t>(sizeof(address)), rv) |
| 110 << ErrnoMessage("write"); | 110 << ErrnoMessage("write"); |
| 111 | 111 |
| 112 // Wait for the parent to say that it’s OK to exit. | 112 // Wait for the parent to say that it’s OK to exit. |
| 113 int read_fd = ReadPipeFD(); | 113 int read_fd = ReadPipeFD(); |
| 114 char c; | 114 char c; |
| 115 rv = ReadFD(read_fd, &c, 1); | 115 rv = ReadFD(read_fd, &c, 1); |
| 116 ASSERT_EQ(1, rv) << ErrnoMessage("read"); | 116 ASSERT_EQ(1, rv) << ErrnoMessage("read"); |
| 117 } | 117 } |
| 118 | 118 |
| 119 private: | |
| 120 DISALLOW_COPY_AND_ASSIGN(ProcessReaderChild); | 119 DISALLOW_COPY_AND_ASSIGN(ProcessReaderChild); |
| 121 }; | 120 }; |
| 122 | 121 |
| 123 TEST(ProcessReader, ChildBasic) { | 122 TEST(ProcessReader, ChildBasic) { |
| 124 ProcessReaderChild process_reader_child; | 123 ProcessReaderChild process_reader_child; |
| 125 process_reader_child.Run(); | 124 process_reader_child.Run(); |
| 126 } | 125 } |
| 127 | 126 |
| 128 // Returns a thread ID given a pthread_t. This wraps pthread_threadid_np() but | 127 // Returns a thread ID given a pthread_t. This wraps pthread_threadid_np() but |
| 129 // that function has a cumbersome interface because it returns a success value. | 128 // that function has a cumbersome interface because it returns a success value. |
| (...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 427 | 426 |
| 428 class ProcessReaderThreadedChild final : public MachMultiprocess { | 427 class ProcessReaderThreadedChild final : public MachMultiprocess { |
| 429 public: | 428 public: |
| 430 explicit ProcessReaderThreadedChild(size_t thread_count) | 429 explicit ProcessReaderThreadedChild(size_t thread_count) |
| 431 : MachMultiprocess(), | 430 : MachMultiprocess(), |
| 432 thread_count_(thread_count) { | 431 thread_count_(thread_count) { |
| 433 } | 432 } |
| 434 | 433 |
| 435 ~ProcessReaderThreadedChild() {} | 434 ~ProcessReaderThreadedChild() {} |
| 436 | 435 |
| 437 protected: | 436 private: |
| 438 void Parent() override { | 437 void MachMultiprocessParent() override { |
| 439 ProcessReader process_reader; | 438 ProcessReader process_reader; |
| 440 ASSERT_TRUE(process_reader.Initialize(ChildTask())); | 439 ASSERT_TRUE(process_reader.Initialize(ChildTask())); |
| 441 | 440 |
| 442 int read_fd = ReadPipeFD(); | 441 int read_fd = ReadPipeFD(); |
| 443 | 442 |
| 444 // Build a map of all expected threads, keyed by each thread’s ID, and with | 443 // Build a map of all expected threads, keyed by each thread’s ID, and with |
| 445 // addresses that should lie somewhere within each thread’s stack as values. | 444 // addresses that should lie somewhere within each thread’s stack as values. |
| 446 // These IDs and addresses all come from the child process via the pipe. | 445 // These IDs and addresses all come from the child process via the pipe. |
| 447 ThreadMap thread_map; | 446 ThreadMap thread_map; |
| 448 for (size_t thread_index = 0; | 447 for (size_t thread_index = 0; |
| (...skipping 30 matching lines...) Expand all Loading... |
| 479 ExpectSeveralThreads(&thread_map, threads, false); | 478 ExpectSeveralThreads(&thread_map, threads, false); |
| 480 | 479 |
| 481 // Tell the child that it’s OK to exit. The child needed to be kept alive | 480 // Tell the child that it’s OK to exit. The child needed to be kept alive |
| 482 // until the parent finished working with it. | 481 // until the parent finished working with it. |
| 483 int write_fd = WritePipeFD(); | 482 int write_fd = WritePipeFD(); |
| 484 char c = '\0'; | 483 char c = '\0'; |
| 485 int rv = WriteFD(write_fd, &c, 1); | 484 int rv = WriteFD(write_fd, &c, 1); |
| 486 ASSERT_EQ(1, rv) << ErrnoMessage("write"); | 485 ASSERT_EQ(1, rv) << ErrnoMessage("write"); |
| 487 } | 486 } |
| 488 | 487 |
| 489 void Child() override { | 488 void MachMultiprocessChild() override { |
| 490 TestThreadPool thread_pool; | 489 TestThreadPool thread_pool; |
| 491 thread_pool.StartThreads(thread_count_); | 490 thread_pool.StartThreads(thread_count_); |
| 492 if (testing::Test::HasFatalFailure()) { | 491 if (testing::Test::HasFatalFailure()) { |
| 493 return; | 492 return; |
| 494 } | 493 } |
| 495 | 494 |
| 496 int write_fd = WritePipeFD(); | 495 int write_fd = WritePipeFD(); |
| 497 | 496 |
| 498 // This thread isn’t part of the thread pool, but the parent will be able | 497 // This thread isn’t part of the thread pool, but the parent will be able |
| 499 // to inspect it. Write an entry for it. | 498 // to inspect it. Write an entry for it. |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 543 << ErrnoMessage("write"); | 542 << ErrnoMessage("write"); |
| 544 } | 543 } |
| 545 | 544 |
| 546 // Wait for the parent to say that it’s OK to exit. | 545 // Wait for the parent to say that it’s OK to exit. |
| 547 int read_fd = ReadPipeFD(); | 546 int read_fd = ReadPipeFD(); |
| 548 char c; | 547 char c; |
| 549 rv = ReadFD(read_fd, &c, 1); | 548 rv = ReadFD(read_fd, &c, 1); |
| 550 ASSERT_EQ(1, rv) << ErrnoMessage("read"); | 549 ASSERT_EQ(1, rv) << ErrnoMessage("read"); |
| 551 } | 550 } |
| 552 | 551 |
| 553 private: | |
| 554 size_t thread_count_; | 552 size_t thread_count_; |
| 555 | 553 |
| 556 DISALLOW_COPY_AND_ASSIGN(ProcessReaderThreadedChild); | 554 DISALLOW_COPY_AND_ASSIGN(ProcessReaderThreadedChild); |
| 557 }; | 555 }; |
| 558 | 556 |
| 559 TEST(ProcessReader, ChildOneThread) { | 557 TEST(ProcessReader, ChildOneThread) { |
| 560 // The main thread plus zero child threads equals one thread. | 558 // The main thread plus zero child threads equals one thread. |
| 561 const size_t kChildThreads = 0; | 559 const size_t kChildThreads = 0; |
| 562 ProcessReaderThreadedChild process_reader_threaded_child(kChildThreads); | 560 ProcessReaderThreadedChild process_reader_threaded_child(kChildThreads); |
| 563 process_reader_threaded_child.Run(); | 561 process_reader_threaded_child.Run(); |
| 564 } | 562 } |
| 565 | 563 |
| 566 TEST(ProcessReader, ChildSeveralThreads) { | 564 TEST(ProcessReader, ChildSeveralThreads) { |
| 567 const size_t kChildThreads = 64; | 565 const size_t kChildThreads = 64; |
| 568 ProcessReaderThreadedChild process_reader_threaded_child(kChildThreads); | 566 ProcessReaderThreadedChild process_reader_threaded_child(kChildThreads); |
| 569 process_reader_threaded_child.Run(); | 567 process_reader_threaded_child.Run(); |
| 570 } | 568 } |
| 571 | 569 |
| 572 } // namespace | 570 } // namespace |
| OLD | NEW |