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 16 matching lines...) Expand all Loading... |
27 using namespace crashpad; | 27 using namespace crashpad; |
28 using namespace crashpad::test; | 28 using namespace crashpad::test; |
29 | 29 |
30 class TestMultiprocess final : public Multiprocess { | 30 class TestMultiprocess final : public Multiprocess { |
31 public: | 31 public: |
32 TestMultiprocess() : Multiprocess() {} | 32 TestMultiprocess() : Multiprocess() {} |
33 | 33 |
34 ~TestMultiprocess() {} | 34 ~TestMultiprocess() {} |
35 | 35 |
36 private: | 36 private: |
| 37 // Multiprocess: |
| 38 |
37 virtual void MultiprocessParent() override { | 39 virtual void MultiprocessParent() override { |
38 int read_fd = ReadPipeFD(); | 40 int read_fd = ReadPipeFD(); |
39 char c; | 41 char c; |
40 CheckedReadFD(read_fd, &c, 1); | 42 CheckedReadFD(read_fd, &c, 1); |
41 EXPECT_EQ('M', c); | 43 EXPECT_EQ('M', c); |
42 | 44 |
43 pid_t pid; | 45 pid_t pid; |
44 CheckedReadFD(read_fd, &pid, sizeof(pid)); | 46 CheckedReadFD(read_fd, &pid, sizeof(pid)); |
45 EXPECT_EQ(pid, ChildPID()); | 47 EXPECT_EQ(pid, ChildPID()); |
46 | 48 |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
92 } | 94 } |
93 } | 95 } |
94 | 96 |
95 ~TestMultiprocessUnclean() {} | 97 ~TestMultiprocessUnclean() {} |
96 | 98 |
97 private: | 99 private: |
98 int ExitCode() const { | 100 int ExitCode() const { |
99 return type_; | 101 return type_; |
100 } | 102 } |
101 | 103 |
| 104 // Multiprocess: |
| 105 |
102 virtual void MultiprocessParent() override { | 106 virtual void MultiprocessParent() override { |
103 } | 107 } |
104 | 108 |
105 virtual void MultiprocessChild() override { | 109 virtual void MultiprocessChild() override { |
106 if (type_ == kAbort) { | 110 if (type_ == kAbort) { |
107 abort(); | 111 abort(); |
108 } else { | 112 } else { |
109 _exit(ExitCode()); | 113 _exit(ExitCode()); |
110 } | 114 } |
111 } | 115 } |
112 | 116 |
113 TerminationType type_; | 117 TerminationType type_; |
114 | 118 |
115 DISALLOW_COPY_AND_ASSIGN(TestMultiprocessUnclean); | 119 DISALLOW_COPY_AND_ASSIGN(TestMultiprocessUnclean); |
116 }; | 120 }; |
117 | 121 |
118 TEST(Multiprocess, MultiprocessSuccessfulExit) { | 122 TEST(Multiprocess, SuccessfulExit) { |
119 TestMultiprocessUnclean multiprocess(TestMultiprocessUnclean::kExitSuccess); | 123 TestMultiprocessUnclean multiprocess(TestMultiprocessUnclean::kExitSuccess); |
120 multiprocess.Run(); | 124 multiprocess.Run(); |
121 } | 125 } |
122 | 126 |
123 TEST(Multiprocess, MultiprocessUnsuccessfulExit) { | 127 TEST(Multiprocess, UnsuccessfulExit) { |
124 TestMultiprocessUnclean multiprocess(TestMultiprocessUnclean::kExitFailure); | 128 TestMultiprocessUnclean multiprocess(TestMultiprocessUnclean::kExitFailure); |
125 multiprocess.Run(); | 129 multiprocess.Run(); |
126 } | 130 } |
127 | 131 |
128 TEST(Multiprocess, MultiprocessExit2) { | 132 TEST(Multiprocess, Exit2) { |
129 TestMultiprocessUnclean multiprocess(TestMultiprocessUnclean::kExit2); | 133 TestMultiprocessUnclean multiprocess(TestMultiprocessUnclean::kExit2); |
130 multiprocess.Run(); | 134 multiprocess.Run(); |
131 } | 135 } |
132 | 136 |
133 TEST(Multiprocess, MultiprocessAbortSignal) { | 137 TEST(Multiprocess, AbortSignal) { |
134 TestMultiprocessUnclean multiprocess(TestMultiprocessUnclean::kAbort); | 138 TestMultiprocessUnclean multiprocess(TestMultiprocessUnclean::kAbort); |
135 multiprocess.Run(); | 139 multiprocess.Run(); |
136 } | 140 } |
137 | 141 |
| 142 class TestMultiprocessClosePipe final : public Multiprocess { |
| 143 public: |
| 144 enum WhoCloses { |
| 145 kParentCloses = 0, |
| 146 kChildCloses, |
| 147 }; |
| 148 enum WhatCloses { |
| 149 kReadCloses = 0, |
| 150 kWriteCloses, |
| 151 kReadAndWriteClose, |
| 152 }; |
| 153 |
| 154 TestMultiprocessClosePipe(WhoCloses who_closes, WhatCloses what_closes) |
| 155 : Multiprocess(), |
| 156 who_closes_(who_closes), |
| 157 what_closes_(what_closes) { |
| 158 } |
| 159 |
| 160 ~TestMultiprocessClosePipe() {} |
| 161 |
| 162 private: |
| 163 void VerifyInitial() { |
| 164 ASSERT_NE(-1, ReadPipeFD()); |
| 165 ASSERT_NE(-1, WritePipeFD()); |
| 166 } |
| 167 |
| 168 // Verifies that the partner process did what it was supposed to do. This must |
| 169 // only be called when who_closes_ names the partner process, not this |
| 170 // process. |
| 171 // |
| 172 // If the partner was supposed to close its write pipe, the read pipe will be |
| 173 // checked to ensure that it shows end-of-file. |
| 174 // |
| 175 // If the partner was supposed to close its read pipe, the write pipe will be |
| 176 // checked to ensure that a checked write causes death. This can only be done |
| 177 // if the partner also provides some type of signal when it has closed its |
| 178 // read pipe, which is done in the form of it closing its write pipe, causing |
| 179 // the read pipe in this process to show end-of-file. |
| 180 void VerifyPartner() { |
| 181 if (what_closes_ == kWriteCloses) { |
| 182 CheckedReadFDAtEOF(ReadPipeFD()); |
| 183 } else if (what_closes_ == kReadAndWriteClose) { |
| 184 CheckedReadFDAtEOF(ReadPipeFD()); |
| 185 char c = '\0'; |
| 186 |
| 187 // This will raise SIGPIPE. If fatal (the normal case), that will cause |
| 188 // process termination. If SIGPIPE is being handled somewhere, the write |
| 189 // will still fail and set errno to EPIPE, and CheckedWriteFD() will abort |
| 190 // execution. Regardless of how SIGPIPE is handled, the process will be |
| 191 // terminated. Because the actual termination mechanism is not known, no |
| 192 // regex can be specified. |
| 193 EXPECT_DEATH(CheckedWriteFD(WritePipeFD(), &c, 1), ""); |
| 194 } |
| 195 } |
| 196 |
| 197 void Close() { |
| 198 switch (what_closes_) { |
| 199 case kReadCloses: |
| 200 CloseReadPipe(); |
| 201 EXPECT_NE(-1, WritePipeFD()); |
| 202 EXPECT_DEATH(ReadPipeFD(), "fd"); |
| 203 break; |
| 204 case kWriteCloses: |
| 205 CloseWritePipe(); |
| 206 EXPECT_NE(-1, ReadPipeFD()); |
| 207 EXPECT_DEATH(WritePipeFD(), "fd"); |
| 208 break; |
| 209 case kReadAndWriteClose: |
| 210 CloseReadPipe(); |
| 211 CloseWritePipe(); |
| 212 EXPECT_DEATH(ReadPipeFD(), "fd"); |
| 213 EXPECT_DEATH(WritePipeFD(), "fd"); |
| 214 break; |
| 215 } |
| 216 } |
| 217 |
| 218 // Multiprocess: |
| 219 |
| 220 virtual void MultiprocessParent() override { |
| 221 VerifyInitial(); |
| 222 if (testing::Test::HasFatalFailure()) { |
| 223 return; |
| 224 } |
| 225 |
| 226 if (who_closes_ == kParentCloses) { |
| 227 Close(); |
| 228 } else { |
| 229 VerifyPartner(); |
| 230 } |
| 231 } |
| 232 |
| 233 virtual void MultiprocessChild() override { |
| 234 VerifyInitial(); |
| 235 if (testing::Test::HasFatalFailure()) { |
| 236 return; |
| 237 } |
| 238 |
| 239 if (who_closes_ == kChildCloses) { |
| 240 Close(); |
| 241 } else { |
| 242 VerifyPartner(); |
| 243 } |
| 244 } |
| 245 |
| 246 WhoCloses who_closes_; |
| 247 WhatCloses what_closes_; |
| 248 |
| 249 DISALLOW_COPY_AND_ASSIGN(TestMultiprocessClosePipe); |
| 250 }; |
| 251 |
| 252 TEST(MultiprocessDeathTest, ParentClosesReadPipe) { |
| 253 TestMultiprocessClosePipe multiprocess( |
| 254 TestMultiprocessClosePipe::kParentCloses, |
| 255 TestMultiprocessClosePipe::kReadCloses); |
| 256 multiprocess.Run(); |
| 257 } |
| 258 |
| 259 TEST(MultiprocessDeathTest, ParentClosesWritePipe) { |
| 260 TestMultiprocessClosePipe multiprocess( |
| 261 TestMultiprocessClosePipe::kParentCloses, |
| 262 TestMultiprocessClosePipe::kWriteCloses); |
| 263 multiprocess.Run(); |
| 264 } |
| 265 |
| 266 TEST(MultiprocessDeathTest, ParentClosesReadAndWritePipe) { |
| 267 TestMultiprocessClosePipe multiprocess( |
| 268 TestMultiprocessClosePipe::kParentCloses, |
| 269 TestMultiprocessClosePipe::kReadAndWriteClose); |
| 270 multiprocess.Run(); |
| 271 } |
| 272 |
| 273 TEST(MultiprocessDeathTest, ChildClosesReadPipe) { |
| 274 TestMultiprocessClosePipe multiprocess( |
| 275 TestMultiprocessClosePipe::kChildCloses, |
| 276 TestMultiprocessClosePipe::kReadCloses); |
| 277 multiprocess.Run(); |
| 278 } |
| 279 |
| 280 TEST(MultiprocessDeathTest, ChildClosesWritePipe) { |
| 281 TestMultiprocessClosePipe multiprocess( |
| 282 TestMultiprocessClosePipe::kChildCloses, |
| 283 TestMultiprocessClosePipe::kWriteCloses); |
| 284 multiprocess.Run(); |
| 285 } |
| 286 |
| 287 TEST(MultiprocessDeathTest, ChildClosesReadAndWritePipe) { |
| 288 TestMultiprocessClosePipe multiprocess( |
| 289 TestMultiprocessClosePipe::kChildCloses, |
| 290 TestMultiprocessClosePipe::kReadAndWriteClose); |
| 291 multiprocess.Run(); |
| 292 } |
| 293 |
138 } // namespace | 294 } // namespace |
OLD | NEW |