15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
57d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/message_loop/message_pump_libevent.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <errno.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <fcntl.h>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <unistd.h>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/auto_reset.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/observer_list.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/posix/eintr_wrapper.h"
17eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/libevent/event.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_MACOSX)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/mac/scoped_nsautorelease_pool.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Lifecycle of struct event
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Libevent uses two main data structures:
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// struct event_base (of which there is one per message pump), and
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// struct event (of which there is roughly one per socket).
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The socket's struct event is created in
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// MessagePumpLibevent::WatchFileDescriptor(),
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// is owned by the FileDescriptorWatcher, and is destroyed in
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// StopWatchingFileDescriptor().
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// It is moved into and out of lists in struct event_base by
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the libevent functions event_add() and event_del().
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(dkegel):
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// At the moment bad things happen if a FileDescriptorWatcher
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// is active after its MessagePumpLibevent has been destroyed.
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// See MessageLoopTest.FileDescriptorWatcherOutlivesMessageLoop
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Not clear yet whether that situation occurs in practice,
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// but if it does, we need to fix it.
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base {
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Return 0 on success
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Too small a function to bother putting in a library?
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int SetNonBlocking(int fd) {
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int flags = fcntl(fd, F_GETFL, 0);
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (flags == -1)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    flags = 0;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MessagePumpLibevent::FileDescriptorWatcher::FileDescriptorWatcher()
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : event_(NULL),
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pump_(NULL),
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      watcher_(NULL),
57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      weak_factory_(this) {
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MessagePumpLibevent::FileDescriptorWatcher::~FileDescriptorWatcher() {
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (event_) {
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    StopWatchingFileDescriptor();
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MessagePumpLibevent::FileDescriptorWatcher::StopWatchingFileDescriptor() {
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event* e = ReleaseEvent();
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (e == NULL)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // event_del() is a no-op if the event isn't active.
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = event_del(e);
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete e;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pump_ = NULL;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  watcher_ = NULL;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (rv == 0);
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessagePumpLibevent::FileDescriptorWatcher::Init(event *e) {
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(e);
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!event_);
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event_ = e;
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)event *MessagePumpLibevent::FileDescriptorWatcher::ReleaseEvent() {
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct event *e = event_;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event_ = NULL;
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return e;
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessagePumpLibevent::FileDescriptorWatcher::OnFileCanReadWithoutBlocking(
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int fd, MessagePumpLibevent* pump) {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Since OnFileCanWriteWithoutBlocking() gets called first, it can stop
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // watching the file descriptor.
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!watcher_)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pump->WillProcessIOEvent();
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  watcher_->OnFileCanReadWithoutBlocking(fd);
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pump->DidProcessIOEvent();
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessagePumpLibevent::FileDescriptorWatcher::OnFileCanWriteWithoutBlocking(
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int fd, MessagePumpLibevent* pump) {
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(watcher_);
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pump->WillProcessIOEvent();
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  watcher_->OnFileCanWriteWithoutBlocking(fd);
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pump->DidProcessIOEvent();
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MessagePumpLibevent::MessagePumpLibevent()
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : keep_running_(true),
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      in_run_(false),
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      processed_io_events_(false),
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      event_base_(event_base_new()),
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      wakeup_pipe_in_(-1),
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      wakeup_pipe_out_(-1) {
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!Init())
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     NOTREACHED();
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MessagePumpLibevent::~MessagePumpLibevent() {
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(wakeup_event_);
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(event_base_);
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event_del(wakeup_event_);
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete wakeup_event_;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (wakeup_pipe_in_ >= 0) {
128a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (IGNORE_EINTR(close(wakeup_pipe_in_)) < 0)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DPLOG(ERROR) << "close";
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (wakeup_pipe_out_ >= 0) {
132a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (IGNORE_EINTR(close(wakeup_pipe_out_)) < 0)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DPLOG(ERROR) << "close";
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event_base_free(event_base_);
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MessagePumpLibevent::WatchFileDescriptor(int fd,
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              bool persistent,
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                              int mode,
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              FileDescriptorWatcher *controller,
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              Watcher *delegate) {
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GE(fd, 0);
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(controller);
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(delegate);
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(mode == WATCH_READ || mode == WATCH_WRITE || mode == WATCH_READ_WRITE);
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // WatchFileDescriptor should be called on the pump thread. It is not
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // threadsafe, and your watcher may never be registered.
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(watch_file_descriptor_caller_checker_.CalledOnValidThread());
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int event_mask = persistent ? EV_PERSIST : 0;
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (mode & WATCH_READ) {
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    event_mask |= EV_READ;
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (mode & WATCH_WRITE) {
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    event_mask |= EV_WRITE;
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<event> evt(controller->ReleaseEvent());
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (evt.get() == NULL) {
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Ownership is transferred to the controller.
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    evt.reset(new event);
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Make sure we don't pick up any funky internal libevent masks.
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int old_interest_mask = evt.get()->ev_events &
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (EV_READ | EV_WRITE | EV_PERSIST);
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Combine old/new event masks.
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    event_mask |= old_interest_mask;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Must disarm the event before we can reuse it.
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    event_del(evt.get());
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // It's illegal to use this function to listen on 2 separate fds with the
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // same |controller|.
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (EVENT_FD(evt.get()) != fd) {
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED() << "FDs don't match" << EVENT_FD(evt.get()) << "!=" << fd;
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Set current interest mask and message pump for this event.
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event_set(evt.get(), fd, event_mask, OnLibeventNotification, controller);
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Tell libevent which message pump this socket will belong to when we add it.
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (event_base_set(event_base_, evt.get())) {
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add this socket to the list of monitored sockets.
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (event_add(evt.get(), NULL)) {
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Transfer ownership of evt to controller.
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  controller->Init(evt.release());
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  controller->set_watcher(delegate);
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  controller->set_pump(this);
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessagePumpLibevent::AddIOObserver(IOObserver *obs) {
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  io_observers_.AddObserver(obs);
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessagePumpLibevent::RemoveIOObserver(IOObserver *obs) {
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  io_observers_.RemoveObserver(obs);
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Tell libevent to break out of inner loop.
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void timer_callback(int fd, short events, void *context)
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event_base_loopbreak((struct event_base *)context);
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Reentrant!
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessagePumpLibevent::Run(Delegate* delegate) {
2205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  AutoReset<bool> auto_reset_keep_running(&keep_running_, true);
2217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  AutoReset<bool> auto_reset_in_run(&in_run_, true);
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // event_base_loopexit() + EVLOOP_ONCE is leaky, see http://crbug.com/25641.
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Instead, make our own timer and reuse it on each call to event_base_loop().
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<event> timer_event(new event);
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (;;) {
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_MACOSX)
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mac::ScopedNSAutoreleasePool autorelease_pool;
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool did_work = delegate->DoWork();
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!keep_running_)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    event_base_loop(event_base_, EVLOOP_NONBLOCK);
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    did_work |= processed_io_events_;
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    processed_io_events_ = false;
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!keep_running_)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    did_work |= delegate->DoDelayedWork(&delayed_work_time_);
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!keep_running_)
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (did_work)
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    did_work = delegate->DoIdleWork();
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!keep_running_)
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (did_work)
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // EVLOOP_ONCE tells libevent to only block once,
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // but to service all pending events when it wakes up.
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (delayed_work_time_.is_null()) {
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      event_base_loop(event_base_, EVLOOP_ONCE);
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      TimeDelta delay = delayed_work_time_ - TimeTicks::Now();
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (delay > TimeDelta()) {
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        struct timeval poll_tv;
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        poll_tv.tv_sec = delay.InSeconds();
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        poll_tv.tv_usec = delay.InMicroseconds() % Time::kMicrosecondsPerSecond;
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        event_set(timer_event.get(), -1, 0, timer_callback, event_base_);
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        event_base_set(event_base_, timer_event.get());
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        event_add(timer_event.get(), &poll_tv);
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        event_base_loop(event_base_, EVLOOP_ONCE);
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        event_del(timer_event.get());
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // It looks like delayed_work_time_ indicates a time in the past, so we
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // need to call DoDelayedWork now.
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        delayed_work_time_ = TimeTicks();
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessagePumpLibevent::Quit() {
2815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  DCHECK(in_run_) << "Quit was called outside of Run!";
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Tell both libevent and Run that they should break out of their loops.
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  keep_running_ = false;
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScheduleWork();
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessagePumpLibevent::ScheduleWork() {
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Tell libevent (in a threadsafe way) that it should break out of its loop.
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char buf = 0;
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nwrite = HANDLE_EINTR(write(wakeup_pipe_in_, &buf, 1));
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(nwrite == 1 || errno == EAGAIN)
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      << "[nwrite:" << nwrite << "] [errno:" << errno << "]";
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessagePumpLibevent::ScheduleDelayedWork(
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const TimeTicks& delayed_work_time) {
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We know that we can't be blocked on Wait right now since this method can
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // only be called on the same thread as Run, so we only need to update our
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // record of how long to sleep when we do sleep.
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delayed_work_time_ = delayed_work_time;
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessagePumpLibevent::WillProcessIOEvent() {
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FOR_EACH_OBSERVER(IOObserver, io_observers_, WillProcessIOEvent());
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessagePumpLibevent::DidProcessIOEvent() {
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FOR_EACH_OBSERVER(IOObserver, io_observers_, DidProcessIOEvent());
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MessagePumpLibevent::Init() {
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int fds[2];
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pipe(fds)) {
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DLOG(ERROR) << "pipe() failed, errno: " << errno;
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (SetNonBlocking(fds[0])) {
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DLOG(ERROR) << "SetNonBlocking for pipe fd[0] failed, errno: " << errno;
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (SetNonBlocking(fds[1])) {
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DLOG(ERROR) << "SetNonBlocking for pipe fd[1] failed, errno: " << errno;
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wakeup_pipe_out_ = fds[0];
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wakeup_pipe_in_ = fds[1];
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  wakeup_event_ = new event;
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event_set(wakeup_event_, wakeup_pipe_out_, EV_READ | EV_PERSIST,
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            OnWakeup, this);
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event_base_set(event_base_, wakeup_event_);
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (event_add(wakeup_event_, 0))
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessagePumpLibevent::OnLibeventNotification(int fd, short flags,
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 void* context) {
3417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  WeakPtr<FileDescriptorWatcher> controller =
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      static_cast<FileDescriptorWatcher*>(context)->weak_factory_.GetWeakPtr();
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(controller.get());
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MessagePumpLibevent* pump = controller->pump();
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pump->processed_io_events_ = true;
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (flags & EV_WRITE) {
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    controller->OnFileCanWriteWithoutBlocking(fd, pump);
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check |controller| in case it's been deleted in
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // controller->OnFileCanWriteWithoutBlocking().
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (controller.get() && flags & EV_READ) {
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    controller->OnFileCanReadWithoutBlocking(fd, pump);
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Called if a byte is received on the wakeup pipe.
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MessagePumpLibevent::OnWakeup(int socket, short flags, void* context) {
3617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  MessagePumpLibevent* that = static_cast<MessagePumpLibevent*>(context);
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(that->wakeup_pipe_out_ == socket);
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Remove and discard the wakeup byte.
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char buf;
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int nread = HANDLE_EINTR(read(socket, &buf, 1));
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(nread, 1);
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  that->processed_io_events_ = true;
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Tell libevent to break out of inner loop.
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  event_base_loopbreak(that->event_base_);
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace base
374