1b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Use of this source code is governed by a BSD-style license that can be
3b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// found in the LICENSE file.
4b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
5b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/message_loop/message_pump_libevent.h"
6b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
7b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include <errno.h>
8b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include <unistd.h>
9b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
1094ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez#include <memory>
1194ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez
12b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/auto_reset.h"
13b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/compiler_specific.h"
140d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko#include "base/files/file_util.h"
15b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/logging.h"
16b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/observer_list.h"
17b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/posix/eintr_wrapper.h"
1894ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez#include "base/third_party/libevent/event.h"
19b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/time/time.h"
20b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/trace_event/trace_event.h"
210d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko#include "build/build_config.h"
22b910a63ff3111067e79c016f40a7c1baac943405Daniel Erat
23b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#if defined(OS_MACOSX)
24b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/mac/scoped_nsautorelease_pool.h"
25b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#endif
26b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
27b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Lifecycle of struct event
28b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Libevent uses two main data structures:
29b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// struct event_base (of which there is one per message pump), and
30b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// struct event (of which there is roughly one per socket).
31b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// The socket's struct event is created in
32b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// MessagePumpLibevent::WatchFileDescriptor(),
33b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// is owned by the FileDescriptorWatcher, and is destroyed in
34b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// StopWatchingFileDescriptor().
35b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// It is moved into and out of lists in struct event_base by
36b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// the libevent functions event_add() and event_del().
37b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat//
38b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// TODO(dkegel):
39b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// At the moment bad things happen if a FileDescriptorWatcher
40b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// is active after its MessagePumpLibevent has been destroyed.
41b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// See MessageLoopTest.FileDescriptorWatcherOutlivesMessageLoop
42b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Not clear yet whether that situation occurs in practice,
43b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// but if it does, we need to fix it.
44b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
45b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratnamespace base {
46b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
47b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratMessagePumpLibevent::FileDescriptorWatcher::FileDescriptorWatcher()
48b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    : event_(NULL),
49b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      pump_(NULL),
50b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      watcher_(NULL),
510d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko      was_destroyed_(NULL) {
52b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
53b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
54b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratMessagePumpLibevent::FileDescriptorWatcher::~FileDescriptorWatcher() {
55b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  if (event_) {
56b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    StopWatchingFileDescriptor();
57b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
580d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko  if (was_destroyed_) {
590d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko    DCHECK(!*was_destroyed_);
600d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko    *was_destroyed_ = true;
610d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko  }
62b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
63b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
64b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratbool MessagePumpLibevent::FileDescriptorWatcher::StopWatchingFileDescriptor() {
65b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  event* e = ReleaseEvent();
66b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  if (e == NULL)
67b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    return true;
68b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
69b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // event_del() is a no-op if the event isn't active.
70b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  int rv = event_del(e);
71b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  delete e;
72b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  pump_ = NULL;
73b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  watcher_ = NULL;
74b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  return (rv == 0);
75b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
76b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
77b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid MessagePumpLibevent::FileDescriptorWatcher::Init(event *e) {
78b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  DCHECK(e);
79b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  DCHECK(!event_);
80b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
81b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  event_ = e;
82b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
83b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
84b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratevent *MessagePumpLibevent::FileDescriptorWatcher::ReleaseEvent() {
85b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  struct event *e = event_;
86b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  event_ = NULL;
87b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  return e;
88b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
89b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
90b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid MessagePumpLibevent::FileDescriptorWatcher::OnFileCanReadWithoutBlocking(
9194ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez    int fd,
9294ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez    MessagePumpLibevent*) {
93b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Since OnFileCanWriteWithoutBlocking() gets called first, it can stop
94b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // watching the file descriptor.
95b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  if (!watcher_)
96b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    return;
97b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  watcher_->OnFileCanReadWithoutBlocking(fd);
98b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
99b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
100b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid MessagePumpLibevent::FileDescriptorWatcher::OnFileCanWriteWithoutBlocking(
10194ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez    int fd,
10294ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez    MessagePumpLibevent*) {
103b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  DCHECK(watcher_);
104b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  watcher_->OnFileCanWriteWithoutBlocking(fd);
105b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
106b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
107b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratMessagePumpLibevent::MessagePumpLibevent()
108b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    : keep_running_(true),
109b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      in_run_(false),
110b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      processed_io_events_(false),
111b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      event_base_(event_base_new()),
112b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      wakeup_pipe_in_(-1),
113b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      wakeup_pipe_out_(-1) {
114b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  if (!Init())
115b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat     NOTREACHED();
116b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
117b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
118b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratMessagePumpLibevent::~MessagePumpLibevent() {
119b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  DCHECK(wakeup_event_);
120b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  DCHECK(event_base_);
121b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  event_del(wakeup_event_);
122b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  delete wakeup_event_;
123b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  if (wakeup_pipe_in_ >= 0) {
124b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    if (IGNORE_EINTR(close(wakeup_pipe_in_)) < 0)
125b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      DPLOG(ERROR) << "close";
126b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
127b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  if (wakeup_pipe_out_ >= 0) {
128b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    if (IGNORE_EINTR(close(wakeup_pipe_out_)) < 0)
129b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      DPLOG(ERROR) << "close";
130b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
131b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  event_base_free(event_base_);
132b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
133b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
134b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratbool MessagePumpLibevent::WatchFileDescriptor(int fd,
135b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                              bool persistent,
136b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                              int mode,
137b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                              FileDescriptorWatcher *controller,
138b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                              Watcher *delegate) {
139b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  DCHECK_GE(fd, 0);
140b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  DCHECK(controller);
141b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  DCHECK(delegate);
142b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  DCHECK(mode == WATCH_READ || mode == WATCH_WRITE || mode == WATCH_READ_WRITE);
143b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // WatchFileDescriptor should be called on the pump thread. It is not
144b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // threadsafe, and your watcher may never be registered.
145b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  DCHECK(watch_file_descriptor_caller_checker_.CalledOnValidThread());
146b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
147b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  int event_mask = persistent ? EV_PERSIST : 0;
148b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  if (mode & WATCH_READ) {
149b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    event_mask |= EV_READ;
150b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
151b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  if (mode & WATCH_WRITE) {
152b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    event_mask |= EV_WRITE;
153b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
154b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
15594ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez  std::unique_ptr<event> evt(controller->ReleaseEvent());
156b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  if (evt.get() == NULL) {
157b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    // Ownership is transferred to the controller.
158b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    evt.reset(new event);
159b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  } else {
160b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    // Make sure we don't pick up any funky internal libevent masks.
161b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    int old_interest_mask = evt.get()->ev_events &
162b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat        (EV_READ | EV_WRITE | EV_PERSIST);
163b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
164b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    // Combine old/new event masks.
165b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    event_mask |= old_interest_mask;
166b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
167b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    // Must disarm the event before we can reuse it.
168b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    event_del(evt.get());
169b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
170b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    // It's illegal to use this function to listen on 2 separate fds with the
171b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    // same |controller|.
172b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    if (EVENT_FD(evt.get()) != fd) {
173b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      NOTREACHED() << "FDs don't match" << EVENT_FD(evt.get()) << "!=" << fd;
174b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      return false;
175b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    }
176b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
177b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
178b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Set current interest mask and message pump for this event.
179b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  event_set(evt.get(), fd, event_mask, OnLibeventNotification, controller);
180b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
181b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Tell libevent which message pump this socket will belong to when we add it.
182b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  if (event_base_set(event_base_, evt.get())) {
183b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    return false;
184b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
185b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
186b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Add this socket to the list of monitored sockets.
187b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  if (event_add(evt.get(), NULL)) {
188b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    return false;
189b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
190b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
191b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Transfer ownership of evt to controller.
192b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  controller->Init(evt.release());
193b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
194b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  controller->set_watcher(delegate);
195b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  controller->set_pump(this);
196b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
197b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  return true;
198b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
199b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
200b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Tell libevent to break out of inner loop.
20194ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavezstatic void timer_callback(int /*fd*/, short /*events*/, void* context) {
202b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  event_base_loopbreak((struct event_base *)context);
203b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
204b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
205b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Reentrant!
206b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid MessagePumpLibevent::Run(Delegate* delegate) {
207b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  AutoReset<bool> auto_reset_keep_running(&keep_running_, true);
208b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  AutoReset<bool> auto_reset_in_run(&in_run_, true);
209b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
210b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // event_base_loopexit() + EVLOOP_ONCE is leaky, see http://crbug.com/25641.
211b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Instead, make our own timer and reuse it on each call to event_base_loop().
21294ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavez  std::unique_ptr<event> timer_event(new event);
213b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
214b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  for (;;) {
215b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#if defined(OS_MACOSX)
216b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    mac::ScopedNSAutoreleasePool autorelease_pool;
217b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#endif
218b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
219b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    bool did_work = delegate->DoWork();
220b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    if (!keep_running_)
221b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      break;
222b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
223b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    event_base_loop(event_base_, EVLOOP_NONBLOCK);
224b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    did_work |= processed_io_events_;
225b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    processed_io_events_ = false;
226b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    if (!keep_running_)
227b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      break;
228b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
229b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    did_work |= delegate->DoDelayedWork(&delayed_work_time_);
230b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    if (!keep_running_)
231b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      break;
232b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
233b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    if (did_work)
234b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      continue;
235b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
236b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    did_work = delegate->DoIdleWork();
237b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    if (!keep_running_)
238b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      break;
239b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
240b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    if (did_work)
241b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      continue;
242b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
243b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    // EVLOOP_ONCE tells libevent to only block once,
244b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    // but to service all pending events when it wakes up.
245b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    if (delayed_work_time_.is_null()) {
246b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      event_base_loop(event_base_, EVLOOP_ONCE);
247b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    } else {
248b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      TimeDelta delay = delayed_work_time_ - TimeTicks::Now();
249b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      if (delay > TimeDelta()) {
250b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat        struct timeval poll_tv;
251b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat        poll_tv.tv_sec = delay.InSeconds();
252b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat        poll_tv.tv_usec = delay.InMicroseconds() % Time::kMicrosecondsPerSecond;
253b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat        event_set(timer_event.get(), -1, 0, timer_callback, event_base_);
254b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat        event_base_set(event_base_, timer_event.get());
255b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat        event_add(timer_event.get(), &poll_tv);
256b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat        event_base_loop(event_base_, EVLOOP_ONCE);
257b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat        event_del(timer_event.get());
258b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      } else {
259b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat        // It looks like delayed_work_time_ indicates a time in the past, so we
260b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat        // need to call DoDelayedWork now.
261b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat        delayed_work_time_ = TimeTicks();
262b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      }
263b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    }
264b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
265b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    if (!keep_running_)
266b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      break;
267b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
268b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
269b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
270b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid MessagePumpLibevent::Quit() {
271b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  DCHECK(in_run_) << "Quit was called outside of Run!";
272b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Tell both libevent and Run that they should break out of their loops.
273b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  keep_running_ = false;
274b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  ScheduleWork();
275b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
276b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
277b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid MessagePumpLibevent::ScheduleWork() {
278b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Tell libevent (in a threadsafe way) that it should break out of its loop.
279b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  char buf = 0;
280b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  int nwrite = HANDLE_EINTR(write(wakeup_pipe_in_, &buf, 1));
281b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  DCHECK(nwrite == 1 || errno == EAGAIN)
282b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat      << "[nwrite:" << nwrite << "] [errno:" << errno << "]";
283b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
284b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
285b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid MessagePumpLibevent::ScheduleDelayedWork(
286b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    const TimeTicks& delayed_work_time) {
287b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // We know that we can't be blocked on Wait right now since this method can
288b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // only be called on the same thread as Run, so we only need to update our
289b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // record of how long to sleep when we do sleep.
290b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  delayed_work_time_ = delayed_work_time;
291b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
292b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
293b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratbool MessagePumpLibevent::Init() {
294b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  int fds[2];
295b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  if (pipe(fds)) {
296b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    DLOG(ERROR) << "pipe() failed, errno: " << errno;
297b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    return false;
298b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
2990d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko  if (!SetNonBlocking(fds[0])) {
300b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    DLOG(ERROR) << "SetNonBlocking for pipe fd[0] failed, errno: " << errno;
301b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    return false;
302b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
3030d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko  if (!SetNonBlocking(fds[1])) {
304b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    DLOG(ERROR) << "SetNonBlocking for pipe fd[1] failed, errno: " << errno;
305b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    return false;
306b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
307b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  wakeup_pipe_out_ = fds[0];
308b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  wakeup_pipe_in_ = fds[1];
309b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
310b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  wakeup_event_ = new event;
311b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  event_set(wakeup_event_, wakeup_pipe_out_, EV_READ | EV_PERSIST,
312b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat            OnWakeup, this);
313b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  event_base_set(event_base_, wakeup_event_);
314b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
315b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  if (event_add(wakeup_event_, 0))
316b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    return false;
317b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  return true;
318b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
319b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
320b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// static
3210d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenkovoid MessagePumpLibevent::OnLibeventNotification(int fd,
3220d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko                                                 short flags,
323b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat                                                 void* context) {
3240d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko  FileDescriptorWatcher* controller =
3250d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko      static_cast<FileDescriptorWatcher*>(context);
3260d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko  DCHECK(controller);
327b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  TRACE_EVENT1("toplevel", "MessagePumpLibevent::OnLibeventNotification",
328b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat               "fd", fd);
329b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
330b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  MessagePumpLibevent* pump = controller->pump();
331b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  pump->processed_io_events_ = true;
332b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
3330d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko  if ((flags & (EV_READ | EV_WRITE)) == (EV_READ | EV_WRITE)) {
3340d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko    // Both callbacks will be called. It is necessary to check that |controller|
3350d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko    // is not destroyed.
3360d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko    bool controller_was_destroyed = false;
3370d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko    controller->was_destroyed_ = &controller_was_destroyed;
338b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    controller->OnFileCanWriteWithoutBlocking(fd, pump);
3390d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko    if (!controller_was_destroyed)
3400d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko      controller->OnFileCanReadWithoutBlocking(fd, pump);
3410d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko    if (!controller_was_destroyed)
3420d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko      controller->was_destroyed_ = nullptr;
3430d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko  } else if (flags & EV_WRITE) {
3440d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko    controller->OnFileCanWriteWithoutBlocking(fd, pump);
3450d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko  } else if (flags & EV_READ) {
346b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat    controller->OnFileCanReadWithoutBlocking(fd, pump);
347b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  }
348b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
349b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
350b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Called if a byte is received on the wakeup pipe.
351b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// static
35294ffa55491333f3dcc701befd0d2652922916d99Luis Hector Chavezvoid MessagePumpLibevent::OnWakeup(int socket, short /*flags*/, void* context) {
353b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  MessagePumpLibevent* that = static_cast<MessagePumpLibevent*>(context);
354b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  DCHECK(that->wakeup_pipe_out_ == socket);
355b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
356b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Remove and discard the wakeup byte.
357b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  char buf;
358b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  int nread = HANDLE_EINTR(read(socket, &buf, 1));
359b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  DCHECK_EQ(nread, 1);
360b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  that->processed_io_events_ = true;
361b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  // Tell libevent to break out of inner loop.
362b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat  event_base_loopbreak(that->event_base_);
363b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}
364b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat
365b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat}  // namespace base
366