message_pump_libevent.cc revision c407dc5cd9bdc5668497f21b26b09d988ab439de
1c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Copyright (c) 2009 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" 13c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/observer_list.h" 14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/scoped_nsautorelease_pool.h" 15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/scoped_ptr.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 65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid MessagePumpLibevent::FileDescriptorWatcher::Init(event *e, 66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool is_persistent) { 67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(e); 68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(event_ == NULL); 69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott is_persistent_ = is_persistent; 71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott event_ = e; 72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottevent *MessagePumpLibevent::FileDescriptorWatcher::ReleaseEvent() { 75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott struct event *e = event_; 76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott event_ = NULL; 77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return e; 78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool MessagePumpLibevent::FileDescriptorWatcher::StopWatchingFileDescriptor() { 81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott event* e = ReleaseEvent(); 82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (e == NULL) 83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // event_del() is a no-op if the event isn't active. 86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int rv = event_del(e); 87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott delete e; 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pump_ = NULL; 89c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch watcher_ = NULL; 90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return (rv == 0); 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 Scott// Called if a byte is received on the wakeup pipe. 108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid MessagePumpLibevent::OnWakeup(int socket, short flags, void* context) { 109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott base::MessagePumpLibevent* that = 110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott static_cast<base::MessagePumpLibevent*>(context); 111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(that->wakeup_pipe_out_ == socket); 112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Remove and discard the wakeup byte. 114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott char buf; 115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int nread = HANDLE_EINTR(read(socket, &buf, 1)); 116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_EQ(nread, 1); 117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Tell libevent to break out of inner loop. 118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott event_base_loopbreak(that->event_base_); 119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottMessagePumpLibevent::MessagePumpLibevent() 122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott : keep_running_(true), 123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott in_run_(false), 124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott event_base_(event_base_new()), 125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott wakeup_pipe_in_(-1), 126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott wakeup_pipe_out_(-1) { 127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!Init()) 128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NOTREACHED(); 129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool MessagePumpLibevent::Init() { 132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int fds[2]; 133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (pipe(fds)) { 134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DLOG(ERROR) << "pipe() failed, errno: " << errno; 135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (SetNonBlocking(fds[0])) { 138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DLOG(ERROR) << "SetNonBlocking for pipe fd[0] failed, errno: " << errno; 139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (SetNonBlocking(fds[1])) { 142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DLOG(ERROR) << "SetNonBlocking for pipe fd[1] failed, errno: " << errno; 143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott wakeup_pipe_out_ = fds[0]; 146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott wakeup_pipe_in_ = fds[1]; 147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott wakeup_event_ = new event; 149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott event_set(wakeup_event_, wakeup_pipe_out_, EV_READ | EV_PERSIST, 150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott OnWakeup, this); 151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott event_base_set(event_base_, wakeup_event_); 152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 153c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (event_add(wakeup_event_, 0)) 154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottMessagePumpLibevent::~MessagePumpLibevent() { 159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(wakeup_event_); 160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(event_base_); 161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott event_del(wakeup_event_); 162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott delete wakeup_event_; 163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (wakeup_pipe_in_ >= 0) { 164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (HANDLE_EINTR(close(wakeup_pipe_in_)) < 0) 165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PLOG(ERROR) << "close"; 166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (wakeup_pipe_out_ >= 0) { 168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (HANDLE_EINTR(close(wakeup_pipe_out_)) < 0) 169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PLOG(ERROR) << "close"; 170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 171c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott event_base_free(event_base_); 172c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 173c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 174c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool MessagePumpLibevent::WatchFileDescriptor(int fd, 175c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool persistent, 176c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Mode mode, 177c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott FileDescriptorWatcher *controller, 178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Watcher *delegate) { 179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_GE(fd, 0); 180c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(controller); 181c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(delegate); 182c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(mode == WATCH_READ || mode == WATCH_WRITE || mode == WATCH_READ_WRITE); 183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int event_mask = persistent ? EV_PERSIST : 0; 185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if ((mode & WATCH_READ) != 0) { 186c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott event_mask |= EV_READ; 187c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 188c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if ((mode & WATCH_WRITE) != 0) { 189c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott event_mask |= EV_WRITE; 190c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 191c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 192c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott scoped_ptr<event> evt(controller->ReleaseEvent()); 193c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (evt.get() == NULL) { 194c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Ownership is transferred to the controller. 195c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott evt.reset(new event); 196c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 197c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Make sure we don't pick up any funky internal libevent masks. 198c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int old_interest_mask = evt.get()->ev_events & 199c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (EV_READ | EV_WRITE | EV_PERSIST); 200c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 201c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Combine old/new event masks. 202c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott event_mask |= old_interest_mask; 203c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 204c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Must disarm the event before we can reuse it. 205c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott event_del(evt.get()); 206c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 207c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // It's illegal to use this function to listen on 2 separate fds with the 208c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // same |controller|. 209c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (EVENT_FD(evt.get()) != fd) { 210c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott NOTREACHED() << "FDs don't match" << EVENT_FD(evt.get()) << "!=" << fd; 211c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 212c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 213c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 214c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 215c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Set current interest mask and message pump for this event. 216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch event_set(evt.get(), fd, event_mask, OnLibeventNotification, controller); 217c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 218c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Tell libevent which message pump this socket will belong to when we add it. 219c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (event_base_set(event_base_, evt.get()) != 0) { 220c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 221c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 222c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 223c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Add this socket to the list of monitored sockets. 224c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (event_add(evt.get(), NULL) != 0) { 225c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 226c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 227c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 228c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Transfer ownership of evt to controller. 229c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott controller->Init(evt.release(), persistent); 230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch controller->set_watcher(delegate); 232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch controller->set_pump(this); 233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 234c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 235c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 236c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 237c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid MessagePumpLibevent::OnLibeventNotification(int fd, short flags, 238c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void* context) { 239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FileDescriptorWatcher* controller = 240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static_cast<FileDescriptorWatcher*>(context); 241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MessagePumpLibevent* pump = controller->pump(); 243c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 244c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (flags & EV_WRITE) { 245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch controller->OnFileCanWriteWithoutBlocking(fd, pump); 246c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 247c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (flags & EV_READ) { 248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch controller->OnFileCanReadWithoutBlocking(fd, pump); 249c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 250c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 251c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 252c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Tell libevent to break out of inner loop. 253c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic void timer_callback(int fd, short events, void *context) 254c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott{ 255c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott event_base_loopbreak((struct event_base *)context); 256c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 257c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 258c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Reentrant! 259c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid MessagePumpLibevent::Run(Delegate* delegate) { 260c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(keep_running_) << "Quit must have been called outside of Run!"; 261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch AutoReset<bool> auto_reset_in_run(&in_run_, true); 262c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 263c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // event_base_loopexit() + EVLOOP_ONCE is leaky, see http://crbug.com/25641. 264c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Instead, make our own timer and reuse it on each call to event_base_loop(). 265c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott scoped_ptr<event> timer_event(new event); 266c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 267c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (;;) { 268c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ScopedNSAutoreleasePool autorelease_pool; 269c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 270c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool did_work = delegate->DoWork(); 271c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!keep_running_) 272c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 273c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 274c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott did_work |= delegate->DoDelayedWork(&delayed_work_time_); 275c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!keep_running_) 276c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 277c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 278c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (did_work) 279c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott continue; 280c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 281c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott did_work = delegate->DoIdleWork(); 282c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!keep_running_) 283c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 284c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 285c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (did_work) 286c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott continue; 287c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 288c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // EVLOOP_ONCE tells libevent to only block once, 289c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // but to service all pending events when it wakes up. 290c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (delayed_work_time_.is_null()) { 291c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott event_base_loop(event_base_, EVLOOP_ONCE); 292c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 293c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott TimeDelta delay = delayed_work_time_ - Time::Now(); 294c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (delay > TimeDelta()) { 295c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott struct timeval poll_tv; 296c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott poll_tv.tv_sec = delay.InSeconds(); 297c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott poll_tv.tv_usec = delay.InMicroseconds() % Time::kMicrosecondsPerSecond; 298c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott event_set(timer_event.get(), -1, 0, timer_callback, event_base_); 299c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott event_base_set(event_base_, timer_event.get()); 300c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott event_add(timer_event.get(), &poll_tv); 301c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott event_base_loop(event_base_, EVLOOP_ONCE); 302c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott event_del(timer_event.get()); 303c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 304c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // It looks like delayed_work_time_ indicates a time in the past, so we 305c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // need to call DoDelayedWork now. 306c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott delayed_work_time_ = Time(); 307c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 308c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 309c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 310c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 311c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott keep_running_ = true; 312c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 313c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 314c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid MessagePumpLibevent::Quit() { 315c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(in_run_); 316c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Tell both libevent and Run that they should break out of their loops. 317c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott keep_running_ = false; 318c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ScheduleWork(); 319c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 320c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 321c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid MessagePumpLibevent::ScheduleWork() { 322c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Tell libevent (in a threadsafe way) that it should break out of its loop. 323c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott char buf = 0; 324c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int nwrite = HANDLE_EINTR(write(wakeup_pipe_in_, &buf, 1)); 325c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(nwrite == 1 || errno == EAGAIN) 326c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott << "[nwrite:" << nwrite << "] [errno:" << errno << "]"; 327c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 328c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 329c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid MessagePumpLibevent::ScheduleDelayedWork(const Time& delayed_work_time) { 330c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // We know that we can't be blocked on Wait right now since this method can 331c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // only be called on the same thread as Run, so we only need to update our 332c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // record of how long to sleep when we do sleep. 333c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott delayed_work_time_ = delayed_work_time; 334c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 335c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 336c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MessagePumpLibevent::AddIOObserver(IOObserver *obs) { 337c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch io_observers_.AddObserver(obs); 338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MessagePumpLibevent::RemoveIOObserver(IOObserver *obs) { 341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch io_observers_.RemoveObserver(obs); 342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 344c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MessagePumpLibevent::WillProcessIOEvent() { 345c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FOR_EACH_OBSERVER(IOObserver, io_observers_, WillProcessIOEvent()); 346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 347c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid MessagePumpLibevent::DidProcessIOEvent() { 349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FOR_EACH_OBSERVER(IOObserver, io_observers_, DidProcessIOEvent()); 350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 352c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} // namespace base 353