• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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