Ejemplo n.º 1
0
void EventHandler::ensureNotRegistered(const char* fn) {
  // Neither the EventBase nor file descriptor may be changed while the
  // handler is registered.  Treat it as a programmer bug and abort the program
  // if this requirement is violated.
  if (isHandlerRegistered()) {
    LOG(ERROR) << fn << " called on registered handler; aborting";
    abort();
  }
}
Ejemplo n.º 2
0
void EventHandler::attachEventBase(EventBase* eventBase) {
  // attachEventBase() may only be called on detached handlers
  assert(event_.ev_base == nullptr);
  assert(!isHandlerRegistered());
  // This must be invoked from the EventBase's thread
  assert(eventBase->isInEventBaseThread());

  setEventBase(eventBase);
}
Ejemplo n.º 3
0
void AsyncPipeWriter::closeOnEmpty() {
  VLOG(5) << "close on empty";
  if (queue_.empty()) {
    closeNow();
  } else {
    closeOnEmpty_ = true;
    CHECK(isHandlerRegistered());
  }
}
Ejemplo n.º 4
0
bool EventHandler::registerImpl(uint16_t events, bool internal) {
  assert(event_.ev_base != nullptr);

  // We have to unregister the event before we can change the event flags
  if (isHandlerRegistered()) {
    // If the new events are the same are the same as the already registered
    // flags, we don't have to do anything.  Just return.
    auto flags = event_ref_flags(&event_);
    if (events == event_.ev_events &&
        static_cast<bool>(flags & EVLIST_INTERNAL) == internal) {
      return true;
    }

    event_del(&event_);
  }

  // Update the event flags
  // Unfortunately, event_set() resets the event_base, so we have to remember
  // it before hand, then pass it back into event_base_set() afterwards
  struct event_base* evb = event_.ev_base;
  event_set(&event_, event_.ev_fd, events,
            &EventHandler::libeventCallback, this);
  event_base_set(evb, &event_);

  // Set EVLIST_INTERNAL if this is an internal event
  if (internal) {
    event_ref_flags(&event_) |= EVLIST_INTERNAL;
  }

  // Add the event.
  //
  // Although libevent allows events to wait on both I/O and a timeout,
  // we intentionally don't allow an EventHandler to also use a timeout.
  // Callers must maintain a separate AsyncTimeout object if they want a
  // timeout.
  //
  // Otherwise, it is difficult to handle persistent events properly.  (The I/O
  // event and timeout may both fire together the same time around the event
  // loop.  Normally we would want to inform the caller of the I/O event first,
  // then the timeout.  However, it is difficult to do this properly since the
  // I/O callback could delete the EventHandler.)  Additionally, if a caller
  // uses the same struct event for both I/O and timeout, and they just want to
  // reschedule the timeout, libevent currently makes an epoll_ctl() call even
  // if the I/O event flags haven't changed.  Using a separate event struct is
  // therefore slightly more efficient in this case (although it does take up
  // more space).
  if (event_add(&event_, nullptr) < 0) {
    LOG(ERROR) << "EventBase: failed to register event handler for fd "
               << event_.ev_fd << ": " << strerror(errno);
    // Call event_del() to make sure the event is completely uninstalled
    event_del(&event_);
    return false;
  }

  return true;
}
Ejemplo n.º 5
0
void AsyncPipeWriter::write(unique_ptr<folly::IOBuf> buf,
                            AsyncWriter::WriteCallback* callback) {
  if (closed()) {
    if (callback) {
      AsyncSocketException ex(AsyncSocketException::NOT_OPEN,
                              "attempt to write to closed pipe");
      callback->writeErr(0, ex);
    }
    return;
  }
  bool wasEmpty = (queue_.empty());
  folly::IOBufQueue iobq;
  iobq.append(std::move(buf));
  std::pair<folly::IOBufQueue, AsyncWriter::WriteCallback*> p(
    std::move(iobq), callback);
  queue_.emplace_back(std::move(p));
  if (wasEmpty)  {
    handleWrite();
  } else {
    CHECK(!queue_.empty());
    CHECK(isHandlerRegistered());
  }
}
Ejemplo n.º 6
0
void EventHandler::unregisterHandler() {
  if (isHandlerRegistered()) {
    event_del(&event_);
  }
}
Ejemplo n.º 7
0
void TunIntf::start() {
  if (fd_ != -1 && !isHandlerRegistered()) {
    changeHandlerFD(fd_);
    registerHandler(TEventHandler::READ|TEventHandler::PERSIST);
  }
}