1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be 3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file. 4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/message_pump_libevent.h" 6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <errno.h> 8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <fcntl.h> 9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/auto_reset.h" 11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/eintr_wrapper.h" 12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/logging.h" 13731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "base/mac/scoped_nsautorelease_pool.h" 14ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/scoped_ptr.h" 15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/observer_list.h" 16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/time.h" 17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#if defined(USE_SYSTEM_LIBEVENT) 18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <event.h> 19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#else 20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "third_party/libevent/event.h" 21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif 22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Lifecycle of struct event 24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Libevent uses two main data structures: 25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// struct event_base (of which there is one per message pump), and 26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// struct event (of which there is roughly one per socket). 27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// The socket's struct event is created in 28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// MessagePumpLibevent::WatchFileDescriptor(), 29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// is owned by the FileDescriptorWatcher, and is destroyed in 30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// StopWatchingFileDescriptor(). 31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// It is moved into and out of lists in struct event_base by 32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// the libevent functions event_add() and event_del(). 33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// 34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// TODO(dkegel): 35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// At the moment bad things happen if a FileDescriptorWatcher 36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// is active after its MessagePumpLibevent has been destroyed. 37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// See MessageLoopTest.FileDescriptorWatcherOutlivesMessageLoop 38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Not clear yet whether that situation occurs in practice, 39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// but if it does, we need to fix it. 40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace base { 42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Return 0 on success 44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Too small a function to bother putting in a library? 45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic int SetNonBlocking(int fd) { 46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int flags = fcntl(fd, F_GETFL, 0); 47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (flags == -1) 48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott flags = 0; 49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return fcntl(fd, F_SETFL, flags | O_NONBLOCK); 50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottMessagePumpLibevent::FileDescriptorWatcher::FileDescriptorWatcher() 53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott : is_persistent_(false), 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch event_(NULL), 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pump_(NULL), 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch watcher_(NULL) { 57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottMessagePumpLibevent::FileDescriptorWatcher::~FileDescriptorWatcher() { 60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (event_) { 61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott StopWatchingFileDescriptor(); 62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 6572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbool MessagePumpLibevent::FileDescriptorWatcher::StopWatchingFileDescriptor() { 6672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen event* e = ReleaseEvent(); 6772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (e == NULL) 6872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return true; 6972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 7072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // event_del() is a no-op if the event isn't active. 7172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int rv = event_del(e); 7272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen delete e; 7372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen pump_ = NULL; 7472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen watcher_ = NULL; 7572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return (rv == 0); 7672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 7772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid MessagePumpLibevent::FileDescriptorWatcher::Init(event *e, 79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool is_persistent) { 80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(e); 81dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen DCHECK(!event_); 82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott is_persistent_ = is_persistent; 84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott event_ = e; 85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottevent *MessagePumpLibevent::FileDescriptorWatcher::ReleaseEvent() { 88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott struct event *e = event_; 89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott event_ = NULL; 90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return e; 91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 93c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MessagePumpLibevent::FileDescriptorWatcher::OnFileCanReadWithoutBlocking( 94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int fd, MessagePumpLibevent* pump) { 95c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pump->WillProcessIOEvent(); 96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch watcher_->OnFileCanReadWithoutBlocking(fd); 97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pump->DidProcessIOEvent(); 98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MessagePumpLibevent::FileDescriptorWatcher::OnFileCanWriteWithoutBlocking( 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int fd, MessagePumpLibevent* pump) { 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pump->WillProcessIOEvent(); 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch watcher_->OnFileCanWriteWithoutBlocking(fd); 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pump->DidProcessIOEvent(); 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottMessagePumpLibevent::MessagePumpLibevent() 108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott : keep_running_(true), 109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott in_run_(false), 110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott event_base_(event_base_new()), 111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott wakeup_pipe_in_(-1), 112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott wakeup_pipe_out_(-1) { 113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!Init()) 114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NOTREACHED(); 115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottMessagePumpLibevent::~MessagePumpLibevent() { 118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(wakeup_event_); 119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(event_base_); 120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott event_del(wakeup_event_); 121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott delete wakeup_event_; 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (wakeup_pipe_in_ >= 0) { 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (HANDLE_EINTR(close(wakeup_pipe_in_)) < 0) 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PLOG(ERROR) << "close"; 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (wakeup_pipe_out_ >= 0) { 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (HANDLE_EINTR(close(wakeup_pipe_out_)) < 0) 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PLOG(ERROR) << "close"; 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott event_base_free(event_base_); 131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool MessagePumpLibevent::WatchFileDescriptor(int fd, 134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool persistent, 135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Mode mode, 136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott FileDescriptorWatcher *controller, 137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Watcher *delegate) { 138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_GE(fd, 0); 139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(controller); 140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(delegate); 141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(mode == WATCH_READ || mode == WATCH_WRITE || mode == WATCH_READ_WRITE); 142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int event_mask = persistent ? EV_PERSIST : 0; 144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if ((mode & WATCH_READ) != 0) { 145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott event_mask |= EV_READ; 146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if ((mode & WATCH_WRITE) != 0) { 148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott event_mask |= EV_WRITE; 149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott scoped_ptr<event> evt(controller->ReleaseEvent()); 152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (evt.get() == NULL) { 153c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Ownership is transferred to the controller. 154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott evt.reset(new event); 155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Make sure we don't pick up any funky internal libevent masks. 157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int old_interest_mask = evt.get()->ev_events & 158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (EV_READ | EV_WRITE | EV_PERSIST); 159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Combine old/new event masks. 161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott event_mask |= old_interest_mask; 162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 163c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Must disarm the event before we can reuse it. 164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott event_del(evt.get()); 165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // It's illegal to use this function to listen on 2 separate fds with the 167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // same |controller|. 168c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (EVENT_FD(evt.get()) != fd) { 169c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NOTREACHED() << "FDs don't match" << EVENT_FD(evt.get()) << "!=" << fd; 170c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 171c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 172c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 173c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 174c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Set current interest mask and message pump for this event. 175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch event_set(evt.get(), fd, event_mask, OnLibeventNotification, controller); 176c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 177c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Tell libevent which message pump this socket will belong to when we add it. 178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (event_base_set(event_base_, evt.get()) != 0) { 179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 180c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 181c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 182c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Add this socket to the list of monitored sockets. 183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (event_add(evt.get(), NULL) != 0) { 184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 186c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 187c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Transfer ownership of evt to controller. 188c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott controller->Init(evt.release(), persistent); 189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch controller->set_watcher(delegate); 191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch controller->set_pump(this); 192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 193c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 194c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 195c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 19672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid MessagePumpLibevent::AddIOObserver(IOObserver *obs) { 19772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen io_observers_.AddObserver(obs); 19872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 199c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 20072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid MessagePumpLibevent::RemoveIOObserver(IOObserver *obs) { 20172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen io_observers_.RemoveObserver(obs); 202c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 203c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 204c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Tell libevent to break out of inner loop. 205c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic void timer_callback(int fd, short events, void *context) 206c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott{ 207c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott event_base_loopbreak((struct event_base *)context); 208c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 209c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 210c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Reentrant! 211c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid MessagePumpLibevent::Run(Delegate* delegate) { 212c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(keep_running_) << "Quit must have been called outside of Run!"; 213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch AutoReset<bool> auto_reset_in_run(&in_run_, true); 214c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 215c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // event_base_loopexit() + EVLOOP_ONCE is leaky, see http://crbug.com/25641. 216c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Instead, make our own timer and reuse it on each call to event_base_loop(). 217c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott scoped_ptr<event> timer_event(new event); 218c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 219c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (;;) { 220731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick mac::ScopedNSAutoreleasePool autorelease_pool; 221c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 222c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool did_work = delegate->DoWork(); 223c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!keep_running_) 224c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 225c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 226c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott did_work |= delegate->DoDelayedWork(&delayed_work_time_); 227c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!keep_running_) 228c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 229c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 230c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (did_work) 231c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott continue; 232c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 233c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott did_work = delegate->DoIdleWork(); 234c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!keep_running_) 235c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 236c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 237c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (did_work) 238c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott continue; 239c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 240c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // EVLOOP_ONCE tells libevent to only block once, 241c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // but to service all pending events when it wakes up. 242c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (delayed_work_time_.is_null()) { 243c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott event_base_loop(event_base_, EVLOOP_ONCE); 244c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 245513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch TimeDelta delay = delayed_work_time_ - TimeTicks::Now(); 246c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (delay > TimeDelta()) { 247c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott struct timeval poll_tv; 248c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott poll_tv.tv_sec = delay.InSeconds(); 249c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott poll_tv.tv_usec = delay.InMicroseconds() % Time::kMicrosecondsPerSecond; 250c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott event_set(timer_event.get(), -1, 0, timer_callback, event_base_); 251c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott event_base_set(event_base_, timer_event.get()); 252c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott event_add(timer_event.get(), &poll_tv); 253c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott event_base_loop(event_base_, EVLOOP_ONCE); 254c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott event_del(timer_event.get()); 255c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 256c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // It looks like delayed_work_time_ indicates a time in the past, so we 257c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // need to call DoDelayedWork now. 258513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch delayed_work_time_ = TimeTicks(); 259c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 260c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 261c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 262c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 263c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott keep_running_ = true; 264c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 265c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 266c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid MessagePumpLibevent::Quit() { 267c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(in_run_); 268c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Tell both libevent and Run that they should break out of their loops. 269c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott keep_running_ = false; 270c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ScheduleWork(); 271c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 272c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 273c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid MessagePumpLibevent::ScheduleWork() { 274c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Tell libevent (in a threadsafe way) that it should break out of its loop. 275c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott char buf = 0; 276c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int nwrite = HANDLE_EINTR(write(wakeup_pipe_in_, &buf, 1)); 277c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(nwrite == 1 || errno == EAGAIN) 278c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott << "[nwrite:" << nwrite << "] [errno:" << errno << "]"; 279c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 280c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 281513209b27ff55e2841eac0e4120199c23acce758Ben Murdochvoid MessagePumpLibevent::ScheduleDelayedWork( 282513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch const TimeTicks& delayed_work_time) { 283c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // We know that we can't be blocked on Wait right now since this method can 284c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // only be called on the same thread as Run, so we only need to update our 285c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // record of how long to sleep when we do sleep. 286c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott delayed_work_time_ = delayed_work_time; 287c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 288c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MessagePumpLibevent::WillProcessIOEvent() { 290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FOR_EACH_OBSERVER(IOObserver, io_observers_, WillProcessIOEvent()); 291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MessagePumpLibevent::DidProcessIOEvent() { 294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FOR_EACH_OBSERVER(IOObserver, io_observers_, DidProcessIOEvent()); 295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 29772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbool MessagePumpLibevent::Init() { 29872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int fds[2]; 29972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (pipe(fds)) { 30072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DLOG(ERROR) << "pipe() failed, errno: " << errno; 30172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return false; 30272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 30372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (SetNonBlocking(fds[0])) { 30472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DLOG(ERROR) << "SetNonBlocking for pipe fd[0] failed, errno: " << errno; 30572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return false; 30672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 30772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (SetNonBlocking(fds[1])) { 30872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DLOG(ERROR) << "SetNonBlocking for pipe fd[1] failed, errno: " << errno; 30972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return false; 31072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 31172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen wakeup_pipe_out_ = fds[0]; 31272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen wakeup_pipe_in_ = fds[1]; 31372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 31472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen wakeup_event_ = new event; 31572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen event_set(wakeup_event_, wakeup_pipe_out_, EV_READ | EV_PERSIST, 31672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen OnWakeup, this); 31772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen event_base_set(event_base_, wakeup_event_); 31872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 31972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (event_add(wakeup_event_, 0)) 32072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return false; 32172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return true; 32272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 32372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 32472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// static 32572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid MessagePumpLibevent::OnLibeventNotification(int fd, short flags, 32672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen void* context) { 32772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen FileDescriptorWatcher* controller = 32872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen static_cast<FileDescriptorWatcher*>(context); 32972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 33072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen MessagePumpLibevent* pump = controller->pump(); 33172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 33272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (flags & EV_WRITE) { 33372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen controller->OnFileCanWriteWithoutBlocking(fd, pump); 33472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 33572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (flags & EV_READ) { 33672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen controller->OnFileCanReadWithoutBlocking(fd, pump); 33772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 33872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 33972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 34072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Called if a byte is received on the wakeup pipe. 34172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// static 34272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid MessagePumpLibevent::OnWakeup(int socket, short flags, void* context) { 34372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen base::MessagePumpLibevent* that = 34472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen static_cast<base::MessagePumpLibevent*>(context); 34572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DCHECK(that->wakeup_pipe_out_ == socket); 34672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 34772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Remove and discard the wakeup byte. 34872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen char buf; 34972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen int nread = HANDLE_EINTR(read(socket, &buf, 1)); 35072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen DCHECK_EQ(nread, 1); 35172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen // Tell libevent to break out of inner loop. 35272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen event_base_loopbreak(that->event_base_); 35372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 35472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 355c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} // namespace base 356