1 // Copyright 2017 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5
6 #include <sys/socket.h>
7
8 #include "base/compiler_specific.h"
9 #include "base/files/file_util.h"
10 #include "base/files/scoped_file.h"
11 #include "base/functional/bind.h"
12 #include "base/logging.h"
13 #include "base/memory/ptr_util.h"
14 #include "base/message_loop/message_pump_for_io.h"
15 #include "base/posix/eintr_wrapper.h"
16 #include "base/run_loop.h"
17 #include "base/task/current_thread.h"
18 #include "base/test/gtest_util.h"
19 #include "base/test/task_environment.h"
20 #include "build/build_config.h"
21 #include "testing/gtest/include/gtest/gtest.h"
22
23 namespace base {
24
25 #if !BUILDFLAG(IS_NACL)
26
27 namespace {
28
29 class FdWatchControllerPosixTest : public testing::Test {
30 public:
31 FdWatchControllerPosixTest() = default;
32
33 FdWatchControllerPosixTest(const FdWatchControllerPosixTest&) = delete;
34 FdWatchControllerPosixTest& operator=(const FdWatchControllerPosixTest&) =
35 delete;
36
37 // testing::Test interface.
SetUp()38 void SetUp() override {
39 // Create a file descriptor. Doesn't need to be readable or writable,
40 // as we don't need to actually get any notifications.
41 // pipe() is just the easiest way to do it.
42 int pipefds[2];
43 int err = pipe(pipefds);
44 ASSERT_EQ(0, err);
45 read_fd_ = ScopedFD(pipefds[0]);
46 write_fd_ = ScopedFD(pipefds[1]);
47 }
48
TriggerReadEvent()49 void TriggerReadEvent() {
50 // Write from the other end of the pipe to trigger the event.
51 char c = '\0';
52 EXPECT_EQ(1, HANDLE_EINTR(write(write_fd_.get(), &c, 1)));
53 }
54
55 protected:
56 ScopedFD read_fd_;
57 ScopedFD write_fd_;
58 };
59
60 class TestHandler : public MessagePumpForIO::FdWatcher {
61 public:
OnFileCanReadWithoutBlocking(int fd)62 void OnFileCanReadWithoutBlocking(int fd) override {
63 watcher_to_delete_ = nullptr;
64 is_readable_ = true;
65 RunLoop::QuitCurrentWhenIdleDeprecated();
66 }
OnFileCanWriteWithoutBlocking(int fd)67 void OnFileCanWriteWithoutBlocking(int fd) override {
68 watcher_to_delete_ = nullptr;
69 is_writable_ = true;
70 RunLoop::QuitCurrentWhenIdleDeprecated();
71 }
72
73 bool is_readable_ = false;
74 bool is_writable_ = false;
75
76 // If set then the contained watcher will be deleted on notification.
77 std::unique_ptr<MessagePumpForIO::FdWatchController> watcher_to_delete_;
78 };
79
80 // Watcher that calls specified closures when read/write events occur. Verifies
81 // that each non-null closure passed to this class is called once and only once.
82 // Also resets the read event by reading from the FD.
83 class CallClosureHandler : public MessagePumpForIO::FdWatcher {
84 public:
CallClosureHandler(OnceClosure read_closure,OnceClosure write_closure)85 CallClosureHandler(OnceClosure read_closure, OnceClosure write_closure)
86 : read_closure_(std::move(read_closure)),
87 write_closure_(std::move(write_closure)) {}
88
~CallClosureHandler()89 ~CallClosureHandler() override {
90 EXPECT_TRUE(read_closure_.is_null());
91 EXPECT_TRUE(write_closure_.is_null());
92 }
93
SetReadClosure(OnceClosure read_closure)94 void SetReadClosure(OnceClosure read_closure) {
95 EXPECT_TRUE(read_closure_.is_null());
96 read_closure_ = std::move(read_closure);
97 }
98
SetWriteClosure(OnceClosure write_closure)99 void SetWriteClosure(OnceClosure write_closure) {
100 EXPECT_TRUE(write_closure_.is_null());
101 write_closure_ = std::move(write_closure);
102 }
103
104 // base::WatchableIOMessagePumpPosix::FdWatcher:
OnFileCanReadWithoutBlocking(int fd)105 void OnFileCanReadWithoutBlocking(int fd) override {
106 // Empty the pipe buffer to reset the event. Otherwise libevent
107 // implementation of MessageLoop may call the event handler again even if
108 // |read_closure_| below quits the RunLoop.
109 char c;
110 int result = HANDLE_EINTR(read(fd, &c, 1));
111 if (result == -1) {
112 PLOG(ERROR) << "read";
113 FAIL();
114 }
115 EXPECT_EQ(result, 1);
116
117 ASSERT_FALSE(read_closure_.is_null());
118 std::move(read_closure_).Run();
119 }
120
OnFileCanWriteWithoutBlocking(int fd)121 void OnFileCanWriteWithoutBlocking(int fd) override {
122 ASSERT_FALSE(write_closure_.is_null());
123 std::move(write_closure_).Run();
124 }
125
126 private:
127 OnceClosure read_closure_;
128 OnceClosure write_closure_;
129 };
130
TEST_F(FdWatchControllerPosixTest,FileDescriptorWatcherOutlivesMessageLoop)131 TEST_F(FdWatchControllerPosixTest, FileDescriptorWatcherOutlivesMessageLoop) {
132 // Simulate a MessageLoop that dies before an FileDescriptorWatcher.
133 // This could happen when people use the Singleton pattern or atexit.
134 TestHandler handler;
135
136 // Arrange for watcher to live longer than message loop.
137 MessagePumpForIO::FdWatchController watcher(FROM_HERE);
138 {
139 test::TaskEnvironment env(test::TaskEnvironment::MainThreadType::IO);
140
141 CurrentIOThread::Get()->WatchFileDescriptor(write_fd_.get(), true,
142 MessagePumpForIO::WATCH_WRITE,
143 &watcher, &handler);
144 // Don't run the message loop, just destroy it.
145 }
146
147 ASSERT_FALSE(handler.is_readable_);
148 ASSERT_FALSE(handler.is_writable_);
149 }
150
TEST_F(FdWatchControllerPosixTest,FileDescriptorWatcherDoubleStop)151 TEST_F(FdWatchControllerPosixTest, FileDescriptorWatcherDoubleStop) {
152 // Verify that it's ok to call StopWatchingFileDescriptor().
153
154 // Arrange for message loop to live longer than watcher.
155 test::TaskEnvironment env(test::TaskEnvironment::MainThreadType::IO);
156 {
157 MessagePumpForIO::FdWatchController watcher(FROM_HERE);
158
159 TestHandler handler;
160 CurrentIOThread::Get()->WatchFileDescriptor(write_fd_.get(), true,
161 MessagePumpForIO::WATCH_WRITE,
162 &watcher, &handler);
163 ASSERT_TRUE(watcher.StopWatchingFileDescriptor());
164 ASSERT_TRUE(watcher.StopWatchingFileDescriptor());
165 }
166 }
167
TEST_F(FdWatchControllerPosixTest,FileDescriptorWatcherDeleteInCallback)168 TEST_F(FdWatchControllerPosixTest, FileDescriptorWatcherDeleteInCallback) {
169 // Verify that it is OK to delete the FileDescriptorWatcher from within a
170 // callback.
171 test::TaskEnvironment env(test::TaskEnvironment::MainThreadType::IO);
172
173 TestHandler handler;
174 handler.watcher_to_delete_ =
175 std::make_unique<MessagePumpForIO::FdWatchController>(FROM_HERE);
176
177 CurrentIOThread::Get()->WatchFileDescriptor(
178 write_fd_.get(), true, MessagePumpForIO::WATCH_WRITE,
179 handler.watcher_to_delete_.get(), &handler);
180 RunLoop().Run();
181 }
182
183 // A watcher that owns its controller and will either delete itself or stop
184 // watching the FD after observing the specified event type.
185 class ReaderWriterHandler : public MessagePumpForIO::FdWatcher {
186 public:
187 enum Action {
188 // Just call StopWatchingFileDescriptor().
189 kStopWatching,
190 // Delete |this| and its owned controller.
191 kDelete,
192 };
193 enum ActWhen {
194 // Take the Action after observing a read event.
195 kOnReadEvent,
196 // Take the Action after observing a write event.
197 kOnWriteEvent,
198 };
199
ReaderWriterHandler(Action action,ActWhen when,OnceClosure idle_quit_closure)200 ReaderWriterHandler(Action action,
201 ActWhen when,
202 OnceClosure idle_quit_closure)
203 : action_(action),
204 when_(when),
205 controller_(FROM_HERE),
206 idle_quit_closure_(std::move(idle_quit_closure)) {}
207
208 ReaderWriterHandler(const ReaderWriterHandler&) = delete;
209 ReaderWriterHandler& operator=(const ReaderWriterHandler&) = delete;
210
211 // base::WatchableIOMessagePumpPosix::FdWatcher:
OnFileCanReadWithoutBlocking(int fd)212 void OnFileCanReadWithoutBlocking(int fd) override {
213 if (when_ == kOnReadEvent) {
214 DoAction();
215 } else {
216 char c;
217 EXPECT_EQ(1, HANDLE_EINTR(read(fd, &c, 1)));
218 }
219 }
220
OnFileCanWriteWithoutBlocking(int fd)221 void OnFileCanWriteWithoutBlocking(int fd) override {
222 if (when_ == kOnWriteEvent) {
223 DoAction();
224 } else {
225 char c = '\0';
226 EXPECT_EQ(1, HANDLE_EINTR(write(fd, &c, 1)));
227 }
228 }
229
controller()230 MessagePumpForIO::FdWatchController* controller() { return &controller_; }
231
232 private:
DoAction()233 void DoAction() {
234 OnceClosure idle_quit_closure = std::move(idle_quit_closure_);
235 if (action_ == kDelete) {
236 delete this;
237 } else if (action_ == kStopWatching) {
238 controller_.StopWatchingFileDescriptor();
239 }
240 std::move(idle_quit_closure).Run();
241 }
242
243 Action action_;
244 ActWhen when_;
245 MessagePumpForIO::FdWatchController controller_;
246 OnceClosure idle_quit_closure_;
247 };
248
249 class MessageLoopForIoPosixReadAndWriteTest
250 : public testing::TestWithParam<ReaderWriterHandler::Action> {
251 protected:
CreateSocketPair(ScopedFD * one,ScopedFD * two)252 bool CreateSocketPair(ScopedFD* one, ScopedFD* two) {
253 int fds[2];
254 if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) == -1)
255 return false;
256 one->reset(fds[0]);
257 two->reset(fds[1]);
258 return true;
259 }
260 };
261
262 INSTANTIATE_TEST_SUITE_P(StopWatchingOrDelete,
263 MessageLoopForIoPosixReadAndWriteTest,
264 testing::Values(ReaderWriterHandler::kStopWatching,
265 ReaderWriterHandler::kDelete));
266
267 // Test deleting or stopping watch after a read event for a watcher that is
268 // registered for both read and write.
TEST_P(MessageLoopForIoPosixReadAndWriteTest,AfterRead)269 TEST_P(MessageLoopForIoPosixReadAndWriteTest, AfterRead) {
270 test::TaskEnvironment env(test::TaskEnvironment::MainThreadType::IO);
271 ScopedFD one, two;
272 ASSERT_TRUE(CreateSocketPair(&one, &two));
273
274 RunLoop run_loop;
275 ReaderWriterHandler* handler =
276 new ReaderWriterHandler(GetParam(), ReaderWriterHandler::kOnReadEvent,
277 run_loop.QuitWhenIdleClosure());
278
279 // Trigger a read event on |one| by writing to |two|.
280 char c = '\0';
281 EXPECT_EQ(1, HANDLE_EINTR(write(two.get(), &c, 1)));
282
283 // The triggered read will cause the watcher action to run. |one| would
284 // also be immediately available for writing, so this should not cause a
285 // use-after-free on the |handler|.
286 CurrentIOThread::Get()->WatchFileDescriptor(
287 one.get(), true, MessagePumpForIO::WATCH_READ_WRITE,
288 handler->controller(), handler);
289 run_loop.Run();
290
291 if (GetParam() == ReaderWriterHandler::kStopWatching) {
292 delete handler;
293 }
294 }
295
296 // Test deleting or stopping watch after a write event for a watcher that is
297 // registered for both read and write.
TEST_P(MessageLoopForIoPosixReadAndWriteTest,AfterWrite)298 TEST_P(MessageLoopForIoPosixReadAndWriteTest, AfterWrite) {
299 test::TaskEnvironment env(test::TaskEnvironment::MainThreadType::IO);
300 ScopedFD one, two;
301 ASSERT_TRUE(CreateSocketPair(&one, &two));
302
303 RunLoop run_loop;
304 ReaderWriterHandler* handler =
305 new ReaderWriterHandler(GetParam(), ReaderWriterHandler::kOnWriteEvent,
306 run_loop.QuitWhenIdleClosure());
307
308 // Trigger two read events on |one| by writing to |two|. Because each read
309 // event only reads one char, |one| will be available for reading again after
310 // the first read event is handled.
311 char c = '\0';
312 EXPECT_EQ(1, HANDLE_EINTR(write(two.get(), &c, 1)));
313 EXPECT_EQ(1, HANDLE_EINTR(write(two.get(), &c, 1)));
314
315 // The triggered read and the immediate availability of |one| for writing
316 // should cause both the read and write watchers to be triggered. The
317 // |handler| will do its action in response to the write event, which should
318 // not trigger a use-after-free for the second read that was queued.
319 CurrentIOThread::Get()->WatchFileDescriptor(
320 one.get(), true, MessagePumpForIO::WATCH_READ_WRITE,
321 handler->controller(), handler);
322 run_loop.Run();
323
324 if (GetParam() == ReaderWriterHandler::kStopWatching) {
325 delete handler;
326 }
327 }
328
329 // Verify that basic readable notification works.
TEST_F(FdWatchControllerPosixTest,WatchReadable)330 TEST_F(FdWatchControllerPosixTest, WatchReadable) {
331 test::TaskEnvironment env(test::TaskEnvironment::MainThreadType::IO);
332 TestHandler handler;
333
334 // Watch the pipe for readability.
335 MessagePumpForIO::FdWatchController watcher(FROM_HERE);
336 ASSERT_TRUE(CurrentIOThread::Get()->WatchFileDescriptor(
337 read_fd_.get(), /*persistent=*/false, MessagePumpForIO::WATCH_READ,
338 &watcher, &handler));
339
340 // The pipe should not be readable when first created.
341 RunLoop().RunUntilIdle();
342 ASSERT_FALSE(handler.is_readable_);
343 ASSERT_FALSE(handler.is_writable_);
344
345 TriggerReadEvent();
346
347 // We don't want to assume that the read fd becomes readable the
348 // instant a bytes is written, so Run until quit by an event.
349 RunLoop().Run();
350
351 ASSERT_TRUE(handler.is_readable_);
352 ASSERT_FALSE(handler.is_writable_);
353 }
354
355 // Verify that watching a file descriptor for writability succeeds.
TEST_F(FdWatchControllerPosixTest,WatchWritable)356 TEST_F(FdWatchControllerPosixTest, WatchWritable) {
357 test::TaskEnvironment env(test::TaskEnvironment::MainThreadType::IO);
358 TestHandler handler;
359
360 // Watch the pipe for writability.
361 MessagePumpForIO::FdWatchController watcher(FROM_HERE);
362 ASSERT_TRUE(CurrentIOThread::Get()->WatchFileDescriptor(
363 write_fd_.get(), /*persistent=*/false, MessagePumpForIO::WATCH_WRITE,
364 &watcher, &handler));
365
366 // We should not receive a writable notification until we process events.
367 ASSERT_FALSE(handler.is_readable_);
368 ASSERT_FALSE(handler.is_writable_);
369
370 // The pipe should be writable immediately, but wait for the quit closure
371 // anyway, to be sure.
372 RunLoop().Run();
373
374 ASSERT_FALSE(handler.is_readable_);
375 ASSERT_TRUE(handler.is_writable_);
376 }
377
378 // Verify that RunUntilIdle() receives IO notifications.
TEST_F(FdWatchControllerPosixTest,RunUntilIdle)379 TEST_F(FdWatchControllerPosixTest, RunUntilIdle) {
380 test::TaskEnvironment env(test::TaskEnvironment::MainThreadType::IO);
381 TestHandler handler;
382
383 // Watch the pipe for readability.
384 MessagePumpForIO::FdWatchController watcher(FROM_HERE);
385 ASSERT_TRUE(CurrentIOThread::Get()->WatchFileDescriptor(
386 read_fd_.get(), /*persistent=*/false, MessagePumpForIO::WATCH_READ,
387 &watcher, &handler));
388
389 // The pipe should not be readable when first created.
390 RunLoop().RunUntilIdle();
391 ASSERT_FALSE(handler.is_readable_);
392
393 TriggerReadEvent();
394
395 while (!handler.is_readable_)
396 RunLoop().RunUntilIdle();
397 }
398
StopWatching(MessagePumpForIO::FdWatchController * controller,RunLoop * run_loop)399 void StopWatching(MessagePumpForIO::FdWatchController* controller,
400 RunLoop* run_loop) {
401 controller->StopWatchingFileDescriptor();
402 run_loop->Quit();
403 }
404
405 // Verify that StopWatchingFileDescriptor() works from an event handler.
TEST_F(FdWatchControllerPosixTest,StopFromHandler)406 TEST_F(FdWatchControllerPosixTest, StopFromHandler) {
407 test::TaskEnvironment env(test::TaskEnvironment::MainThreadType::IO);
408 RunLoop run_loop;
409 MessagePumpForIO::FdWatchController watcher(FROM_HERE);
410 CallClosureHandler handler(BindOnce(&StopWatching, &watcher, &run_loop),
411 OnceClosure());
412
413 // Create persistent watcher.
414 ASSERT_TRUE(CurrentIOThread::Get()->WatchFileDescriptor(
415 read_fd_.get(), /*persistent=*/true, MessagePumpForIO::WATCH_READ,
416 &watcher, &handler));
417
418 TriggerReadEvent();
419 run_loop.Run();
420
421 // Trigger the event again. The event handler should not be called again.
422 TriggerReadEvent();
423 RunLoop().RunUntilIdle();
424 }
425
426 // Verify that non-persistent watcher is called only once.
TEST_F(FdWatchControllerPosixTest,NonPersistentWatcher)427 TEST_F(FdWatchControllerPosixTest, NonPersistentWatcher) {
428 test::TaskEnvironment env(test::TaskEnvironment::MainThreadType::IO);
429
430 RunLoop run_loop;
431 CallClosureHandler handler(run_loop.QuitClosure(), OnceClosure());
432
433 // Create a non-persistent watcher.
434 MessagePumpForIO::FdWatchController watcher(FROM_HERE);
435 ASSERT_TRUE(CurrentIOThread::Get()->WatchFileDescriptor(
436 read_fd_.get(), /*persistent=*/false, MessagePumpForIO::WATCH_READ,
437 &watcher, &handler));
438
439 TriggerReadEvent();
440 run_loop.Run();
441
442 // Trigger the event again. handler should not be called again.
443 TriggerReadEvent();
444 RunLoop().RunUntilIdle();
445 }
446
447 // Verify that persistent watcher is called every time the event is triggered.
TEST_F(FdWatchControllerPosixTest,PersistentWatcher)448 TEST_F(FdWatchControllerPosixTest, PersistentWatcher) {
449 test::TaskEnvironment env(test::TaskEnvironment::MainThreadType::IO);
450
451 RunLoop run_loop1;
452 CallClosureHandler handler(run_loop1.QuitClosure(), OnceClosure());
453
454 // Create persistent watcher.
455 MessagePumpForIO::FdWatchController watcher(FROM_HERE);
456 ASSERT_TRUE(CurrentIOThread::Get()->WatchFileDescriptor(
457 read_fd_.get(), /*persistent=*/true, MessagePumpForIO::WATCH_READ,
458 &watcher, &handler));
459
460 TriggerReadEvent();
461 run_loop1.Run();
462
463 RunLoop run_loop2;
464 handler.SetReadClosure(run_loop2.QuitClosure());
465
466 // Trigger the event again. handler should be called now, which will quit
467 // run_loop2.
468 TriggerReadEvent();
469 run_loop2.Run();
470 }
471
StopWatchingAndWatchAgain(MessagePumpForIO::FdWatchController * controller,int fd,MessagePumpForIO::FdWatcher * new_handler,RunLoop * run_loop)472 void StopWatchingAndWatchAgain(MessagePumpForIO::FdWatchController* controller,
473 int fd,
474 MessagePumpForIO::FdWatcher* new_handler,
475 RunLoop* run_loop) {
476 controller->StopWatchingFileDescriptor();
477
478 ASSERT_TRUE(CurrentIOThread::Get()->WatchFileDescriptor(
479 fd, /*persistent=*/true, MessagePumpForIO::WATCH_READ, controller,
480 new_handler));
481
482 run_loop->Quit();
483 }
484
485 // Verify that a watcher can be stopped and reused from an event handler.
TEST_F(FdWatchControllerPosixTest,StopAndRestartFromHandler)486 TEST_F(FdWatchControllerPosixTest, StopAndRestartFromHandler) {
487 test::TaskEnvironment env(test::TaskEnvironment::MainThreadType::IO);
488
489 RunLoop run_loop1;
490 RunLoop run_loop2;
491 CallClosureHandler handler2(run_loop2.QuitClosure(), OnceClosure());
492 MessagePumpForIO::FdWatchController watcher(FROM_HERE);
493
494 CallClosureHandler handler1(BindOnce(&StopWatchingAndWatchAgain, &watcher,
495 read_fd_.get(), &handler2, &run_loop1),
496 OnceClosure());
497
498 // Create persistent watcher.
499 ASSERT_TRUE(CurrentIOThread::Get()->WatchFileDescriptor(
500 read_fd_.get(), /*persistent=*/true, MessagePumpForIO::WATCH_READ,
501 &watcher, &handler1));
502
503 TriggerReadEvent();
504 run_loop1.Run();
505
506 // Trigger the event again. handler2 should be called now, which will quit
507 // run_loop2
508 TriggerReadEvent();
509 run_loop2.Run();
510 }
511
512 // Verify that the pump properly handles a delayed task after an IO event.
TEST_F(FdWatchControllerPosixTest,IoEventThenTimer)513 TEST_F(FdWatchControllerPosixTest, IoEventThenTimer) {
514 test::TaskEnvironment env(test::TaskEnvironment::MainThreadType::IO);
515
516 RunLoop timer_run_loop;
517 env.GetMainThreadTaskRunner()->PostDelayedTask(
518 FROM_HERE, timer_run_loop.QuitClosure(), base::Milliseconds(10));
519
520 RunLoop watcher_run_loop;
521 CallClosureHandler handler(watcher_run_loop.QuitClosure(), OnceClosure());
522
523 // Create a non-persistent watcher.
524 MessagePumpForIO::FdWatchController watcher(FROM_HERE);
525 ASSERT_TRUE(CurrentIOThread::Get()->WatchFileDescriptor(
526 read_fd_.get(), /*persistent=*/false, MessagePumpForIO::WATCH_READ,
527 &watcher, &handler));
528
529 TriggerReadEvent();
530
531 // Normally the IO event will be received before the delayed task is
532 // executed, so this run loop will first handle the IO event and then quit on
533 // the timer.
534 timer_run_loop.Run();
535
536 // Run watcher_run_loop in case the IO event wasn't received before the
537 // delayed task.
538 watcher_run_loop.Run();
539 }
540
541 // Verify that the pipe can handle an IO event after a delayed task.
TEST_F(FdWatchControllerPosixTest,TimerThenIoEvent)542 TEST_F(FdWatchControllerPosixTest, TimerThenIoEvent) {
543 test::TaskEnvironment env(test::TaskEnvironment::MainThreadType::IO);
544
545 // Trigger read event from a delayed task.
546 env.GetMainThreadTaskRunner()->PostDelayedTask(
547 FROM_HERE,
548 BindOnce(&FdWatchControllerPosixTest::TriggerReadEvent, Unretained(this)),
549 Milliseconds(1));
550
551 RunLoop run_loop;
552 CallClosureHandler handler(run_loop.QuitClosure(), OnceClosure());
553
554 // Create a non-persistent watcher.
555 MessagePumpForIO::FdWatchController watcher(FROM_HERE);
556 ASSERT_TRUE(CurrentIOThread::Get()->WatchFileDescriptor(
557 read_fd_.get(), /*persistent=*/false, MessagePumpForIO::WATCH_READ,
558 &watcher, &handler));
559
560 run_loop.Run();
561 }
562
563 } // namespace
564
565 #endif // !BUILDFLAG(IS_NACL)
566
567 } // namespace base
568