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