blob: bf3c7af3e937055f60a62ae0d8a469a30e5470c5 [file] [log] [blame]
[email protected]b1d934a02012-05-14 16:49:201// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]36987e92008-09-18 18:46:262// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "base/message_pump_libevent.h"
6
[email protected]91cb3702009-01-20 21:12:157#include <errno.h>
[email protected]157fd8522009-01-20 22:12:268#include <fcntl.h>
[email protected]b1d934a02012-05-14 16:49:209#include <unistd.h>
[email protected]89836e22008-09-25 20:33:4210
[email protected]5be7da242009-11-20 23:16:2611#include "base/auto_reset.h"
[email protected]8d5f3ac2011-07-20 16:01:3212#include "base/compiler_specific.h"
[email protected]36987e92008-09-18 18:46:2613#include "base/logging.h"
[email protected]29535ff2011-12-06 15:09:5614#if defined(OS_MACOSX)
15#include "base/mac/scoped_nsautorelease_pool.h"
16#endif
[email protected]3b63f8f42011-03-28 01:54:1517#include "base/memory/scoped_ptr.h"
[email protected]9cfb89a2010-06-09 21:20:4118#include "base/observer_list.h"
[email protected]2025d002012-11-14 20:54:3519#include "base/posix/eintr_wrapper.h"
[email protected]36987e92008-09-18 18:46:2620#include "base/time.h"
21#include "third_party/libevent/event.h"
22
[email protected]badf5cf2011-10-29 03:44:4423#if defined(OS_MACOSX)
24#include "base/mac/scoped_nsautorelease_pool.h"
25#endif
26
[email protected]f74c8962009-04-22 20:01:3627// Lifecycle of struct event
28// Libevent uses two main data structures:
29// struct event_base (of which there is one per message pump), and
30// struct event (of which there is roughly one per socket).
31// The socket's struct event is created in
32// MessagePumpLibevent::WatchFileDescriptor(),
33// is owned by the FileDescriptorWatcher, and is destroyed in
34// StopWatchingFileDescriptor().
35// It is moved into and out of lists in struct event_base by
36// the libevent functions event_add() and event_del().
37//
38// TODO(dkegel):
39// At the moment bad things happen if a FileDescriptorWatcher
40// is active after its MessagePumpLibevent has been destroyed.
41// See MessageLoopTest.FileDescriptorWatcherOutlivesMessageLoop
42// Not clear yet whether that situation occurs in practice,
43// but if it does, we need to fix it.
44
[email protected]36987e92008-09-18 18:46:2645namespace base {
46
47// Return 0 on success
48// Too small a function to bother putting in a library?
[email protected]e45e6c02008-12-15 22:02:1749static int SetNonBlocking(int fd) {
50 int flags = fcntl(fd, F_GETFL, 0);
51 if (flags == -1)
52 flags = 0;
53 return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
54}
55
56MessagePumpLibevent::FileDescriptorWatcher::FileDescriptorWatcher()
[email protected]4b4047c42012-06-15 07:40:3357 : event_(NULL),
[email protected]9cfb89a2010-06-09 21:20:4158 pump_(NULL),
[email protected]e4d70962011-07-21 20:16:1159 watcher_(NULL),
[email protected]8d5f3ac2011-07-20 16:01:3260 ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) {
[email protected]e45e6c02008-12-15 22:02:1761}
62
63MessagePumpLibevent::FileDescriptorWatcher::~FileDescriptorWatcher() {
[email protected]f74c8962009-04-22 20:01:3664 if (event_) {
[email protected]e45e6c02008-12-15 22:02:1765 StopWatchingFileDescriptor();
66 }
67}
68
[email protected]eae9c062011-01-11 00:50:5969bool MessagePumpLibevent::FileDescriptorWatcher::StopWatchingFileDescriptor() {
70 event* e = ReleaseEvent();
71 if (e == NULL)
72 return true;
73
74 // event_del() is a no-op if the event isn't active.
75 int rv = event_del(e);
76 delete e;
77 pump_ = NULL;
78 watcher_ = NULL;
79 return (rv == 0);
80}
81
[email protected]4b4047c42012-06-15 07:40:3382void MessagePumpLibevent::FileDescriptorWatcher::Init(event *e) {
[email protected]e45e6c02008-12-15 22:02:1783 DCHECK(e);
[email protected]5d2b4492011-03-01 02:48:0584 DCHECK(!event_);
[email protected]e45e6c02008-12-15 22:02:1785
[email protected]f74c8962009-04-22 20:01:3686 event_ = e;
[email protected]e45e6c02008-12-15 22:02:1787}
88
89event *MessagePumpLibevent::FileDescriptorWatcher::ReleaseEvent() {
[email protected]f74c8962009-04-22 20:01:3690 struct event *e = event_;
91 event_ = NULL;
92 return e;
[email protected]e45e6c02008-12-15 22:02:1793}
94
[email protected]9cfb89a2010-06-09 21:20:4195void MessagePumpLibevent::FileDescriptorWatcher::OnFileCanReadWithoutBlocking(
96 int fd, MessagePumpLibevent* pump) {
[email protected]8d5f3ac2011-07-20 16:01:3297 // Since OnFileCanWriteWithoutBlocking() gets called first, it can stop
98 // watching the file descriptor.
99 if (!watcher_)
100 return;
[email protected]9cfb89a2010-06-09 21:20:41101 pump->WillProcessIOEvent();
102 watcher_->OnFileCanReadWithoutBlocking(fd);
103 pump->DidProcessIOEvent();
104}
105
106void MessagePumpLibevent::FileDescriptorWatcher::OnFileCanWriteWithoutBlocking(
107 int fd, MessagePumpLibevent* pump) {
[email protected]8d5f3ac2011-07-20 16:01:32108 DCHECK(watcher_);
[email protected]9cfb89a2010-06-09 21:20:41109 pump->WillProcessIOEvent();
110 watcher_->OnFileCanWriteWithoutBlocking(fd);
111 pump->DidProcessIOEvent();
112}
113
[email protected]36987e92008-09-18 18:46:26114MessagePumpLibevent::MessagePumpLibevent()
115 : keep_running_(true),
116 in_run_(false),
[email protected]4b4a94f22b2011-07-01 01:55:29117 processed_io_events_(false),
[email protected]36987e92008-09-18 18:46:26118 event_base_(event_base_new()),
119 wakeup_pipe_in_(-1),
120 wakeup_pipe_out_(-1) {
121 if (!Init())
122 NOTREACHED();
123}
124
[email protected]36987e92008-09-18 18:46:26125MessagePumpLibevent::~MessagePumpLibevent() {
126 DCHECK(wakeup_event_);
127 DCHECK(event_base_);
128 event_del(wakeup_event_);
129 delete wakeup_event_;
[email protected]70eb6572010-06-23 00:37:46130 if (wakeup_pipe_in_ >= 0) {
131 if (HANDLE_EINTR(close(wakeup_pipe_in_)) < 0)
[email protected]a42d4632011-10-26 21:48:00132 DPLOG(ERROR) << "close";
[email protected]70eb6572010-06-23 00:37:46133 }
134 if (wakeup_pipe_out_ >= 0) {
135 if (HANDLE_EINTR(close(wakeup_pipe_out_)) < 0)
[email protected]a42d4632011-10-26 21:48:00136 DPLOG(ERROR) << "close";
[email protected]70eb6572010-06-23 00:37:46137 }
[email protected]36987e92008-09-18 18:46:26138 event_base_free(event_base_);
139}
140
[email protected]e45e6c02008-12-15 22:02:17141bool MessagePumpLibevent::WatchFileDescriptor(int fd,
142 bool persistent,
[email protected]d6bafc32012-11-30 17:29:40143 int mode,
[email protected]e45e6c02008-12-15 22:02:17144 FileDescriptorWatcher *controller,
145 Watcher *delegate) {
[email protected]5dcd8652009-12-03 21:38:51146 DCHECK_GE(fd, 0);
[email protected]e45e6c02008-12-15 22:02:17147 DCHECK(controller);
148 DCHECK(delegate);
149 DCHECK(mode == WATCH_READ || mode == WATCH_WRITE || mode == WATCH_READ_WRITE);
[email protected]b4339c3a2011-05-13 16:19:23150 // WatchFileDescriptor should be called on the pump thread. It is not
151 // threadsafe, and your watcher may never be registered.
152 DCHECK(watch_file_descriptor_caller_checker_.CalledOnValidThread());
[email protected]36987e92008-09-18 18:46:26153
[email protected]e45e6c02008-12-15 22:02:17154 int event_mask = persistent ? EV_PERSIST : 0;
[email protected]d6bafc32012-11-30 17:29:40155 if (mode & WATCH_READ) {
[email protected]e45e6c02008-12-15 22:02:17156 event_mask |= EV_READ;
157 }
[email protected]d6bafc32012-11-30 17:29:40158 if (mode & WATCH_WRITE) {
[email protected]e45e6c02008-12-15 22:02:17159 event_mask |= EV_WRITE;
[email protected]900342a2008-12-12 19:55:17160 }
[email protected]36987e92008-09-18 18:46:26161
[email protected]e45e6c02008-12-15 22:02:17162 scoped_ptr<event> evt(controller->ReleaseEvent());
163 if (evt.get() == NULL) {
[email protected]e45e6c02008-12-15 22:02:17164 // Ownership is transferred to the controller.
165 evt.reset(new event);
[email protected]052fd452009-09-23 17:56:25166 } else {
[email protected]052fd452009-09-23 17:56:25167 // Make sure we don't pick up any funky internal libevent masks.
168 int old_interest_mask = evt.get()->ev_events &
169 (EV_READ | EV_WRITE | EV_PERSIST);
170
171 // Combine old/new event masks.
172 event_mask |= old_interest_mask;
173
174 // Must disarm the event before we can reuse it.
175 event_del(evt.get());
[email protected]cee22a92009-09-24 19:45:55176
177 // It's illegal to use this function to listen on 2 separate fds with the
178 // same |controller|.
179 if (EVENT_FD(evt.get()) != fd) {
180 NOTREACHED() << "FDs don't match" << EVENT_FD(evt.get()) << "!=" << fd;
181 return false;
182 }
[email protected]e45e6c02008-12-15 22:02:17183 }
[email protected]900342a2008-12-12 19:55:17184
[email protected]e45e6c02008-12-15 22:02:17185 // Set current interest mask and message pump for this event.
[email protected]9cfb89a2010-06-09 21:20:41186 event_set(evt.get(), fd, event_mask, OnLibeventNotification, controller);
[email protected]e45e6c02008-12-15 22:02:17187
188 // Tell libevent which message pump this socket will belong to when we add it.
[email protected]d6bafc32012-11-30 17:29:40189 if (event_base_set(event_base_, evt.get())) {
[email protected]e45e6c02008-12-15 22:02:17190 return false;
191 }
192
193 // Add this socket to the list of monitored sockets.
[email protected]d6bafc32012-11-30 17:29:40194 if (event_add(evt.get(), NULL)) {
[email protected]e45e6c02008-12-15 22:02:17195 return false;
196 }
197
[email protected]f74c8962009-04-22 20:01:36198 // Transfer ownership of evt to controller.
[email protected]4b4047c42012-06-15 07:40:33199 controller->Init(evt.release());
[email protected]9cfb89a2010-06-09 21:20:41200
201 controller->set_watcher(delegate);
202 controller->set_pump(this);
203
[email protected]e45e6c02008-12-15 22:02:17204 return true;
[email protected]900342a2008-12-12 19:55:17205}
206
[email protected]eae9c062011-01-11 00:50:59207void MessagePumpLibevent::AddIOObserver(IOObserver *obs) {
208 io_observers_.AddObserver(obs);
209}
[email protected]9cfb89a2010-06-09 21:20:41210
[email protected]eae9c062011-01-11 00:50:59211void MessagePumpLibevent::RemoveIOObserver(IOObserver *obs) {
212 io_observers_.RemoveObserver(obs);
[email protected]1d2eb132008-12-08 17:36:06213}
214
[email protected]ba92eb12009-11-06 21:53:52215// Tell libevent to break out of inner loop.
216static void timer_callback(int fd, short events, void *context)
217{
218 event_base_loopbreak((struct event_base *)context);
219}
220
[email protected]36987e92008-09-18 18:46:26221// Reentrant!
222void MessagePumpLibevent::Run(Delegate* delegate) {
223 DCHECK(keep_running_) << "Quit must have been called outside of Run!";
[email protected]997ec9f2012-11-21 04:44:14224 base::AutoReset<bool> auto_reset_in_run(&in_run_, true);
[email protected]36987e92008-09-18 18:46:26225
[email protected]ba92eb12009-11-06 21:53:52226 // event_base_loopexit() + EVLOOP_ONCE is leaky, see http://crbug.com/25641.
227 // Instead, make our own timer and reuse it on each call to event_base_loop().
228 scoped_ptr<event> timer_event(new event);
229
[email protected]36987e92008-09-18 18:46:26230 for (;;) {
[email protected]badf5cf2011-10-29 03:44:44231#if defined(OS_MACOSX)
[email protected]c2818d42010-10-18 02:47:39232 mac::ScopedNSAutoreleasePool autorelease_pool;
[email protected]badf5cf2011-10-29 03:44:44233#endif
[email protected]89836e22008-09-25 20:33:42234
[email protected]36987e92008-09-18 18:46:26235 bool did_work = delegate->DoWork();
236 if (!keep_running_)
237 break;
238
[email protected]4b4a94f22b2011-07-01 01:55:29239 event_base_loop(event_base_, EVLOOP_NONBLOCK);
240 did_work |= processed_io_events_;
241 processed_io_events_ = false;
242 if (!keep_running_)
243 break;
244
[email protected]36987e92008-09-18 18:46:26245 did_work |= delegate->DoDelayedWork(&delayed_work_time_);
246 if (!keep_running_)
247 break;
248
249 if (did_work)
250 continue;
251
252 did_work = delegate->DoIdleWork();
253 if (!keep_running_)
254 break;
255
256 if (did_work)
257 continue;
258
259 // EVLOOP_ONCE tells libevent to only block once,
260 // but to service all pending events when it wakes up.
261 if (delayed_work_time_.is_null()) {
262 event_base_loop(event_base_, EVLOOP_ONCE);
263 } else {
[email protected]7e7fab42010-11-06 22:23:29264 TimeDelta delay = delayed_work_time_ - TimeTicks::Now();
[email protected]36987e92008-09-18 18:46:26265 if (delay > TimeDelta()) {
266 struct timeval poll_tv;
267 poll_tv.tv_sec = delay.InSeconds();
268 poll_tv.tv_usec = delay.InMicroseconds() % Time::kMicrosecondsPerSecond;
[email protected]ba92eb12009-11-06 21:53:52269 event_set(timer_event.get(), -1, 0, timer_callback, event_base_);
270 event_base_set(event_base_, timer_event.get());
271 event_add(timer_event.get(), &poll_tv);
[email protected]36987e92008-09-18 18:46:26272 event_base_loop(event_base_, EVLOOP_ONCE);
[email protected]ba92eb12009-11-06 21:53:52273 event_del(timer_event.get());
[email protected]36987e92008-09-18 18:46:26274 } else {
275 // It looks like delayed_work_time_ indicates a time in the past, so we
276 // need to call DoDelayedWork now.
[email protected]7e7fab42010-11-06 22:23:29277 delayed_work_time_ = TimeTicks();
[email protected]36987e92008-09-18 18:46:26278 }
279 }
280 }
281
282 keep_running_ = true;
[email protected]36987e92008-09-18 18:46:26283}
284
285void MessagePumpLibevent::Quit() {
286 DCHECK(in_run_);
287 // Tell both libevent and Run that they should break out of their loops.
288 keep_running_ = false;
289 ScheduleWork();
290}
291
292void MessagePumpLibevent::ScheduleWork() {
293 // Tell libevent (in a threadsafe way) that it should break out of its loop.
294 char buf = 0;
[email protected]157c61b2009-05-01 21:37:31295 int nwrite = HANDLE_EINTR(write(wakeup_pipe_in_, &buf, 1));
[email protected]3fae2282009-03-17 22:26:06296 DCHECK(nwrite == 1 || errno == EAGAIN)
297 << "[nwrite:" << nwrite << "] [errno:" << errno << "]";
[email protected]36987e92008-09-18 18:46:26298}
299
[email protected]7e7fab42010-11-06 22:23:29300void MessagePumpLibevent::ScheduleDelayedWork(
301 const TimeTicks& delayed_work_time) {
[email protected]36987e92008-09-18 18:46:26302 // We know that we can't be blocked on Wait right now since this method can
303 // only be called on the same thread as Run, so we only need to update our
304 // record of how long to sleep when we do sleep.
305 delayed_work_time_ = delayed_work_time;
306}
307
[email protected]9cfb89a2010-06-09 21:20:41308void MessagePumpLibevent::WillProcessIOEvent() {
309 FOR_EACH_OBSERVER(IOObserver, io_observers_, WillProcessIOEvent());
310}
311
312void MessagePumpLibevent::DidProcessIOEvent() {
313 FOR_EACH_OBSERVER(IOObserver, io_observers_, DidProcessIOEvent());
314}
315
[email protected]eae9c062011-01-11 00:50:59316bool MessagePumpLibevent::Init() {
317 int fds[2];
318 if (pipe(fds)) {
319 DLOG(ERROR) << "pipe() failed, errno: " << errno;
320 return false;
321 }
322 if (SetNonBlocking(fds[0])) {
323 DLOG(ERROR) << "SetNonBlocking for pipe fd[0] failed, errno: " << errno;
324 return false;
325 }
326 if (SetNonBlocking(fds[1])) {
327 DLOG(ERROR) << "SetNonBlocking for pipe fd[1] failed, errno: " << errno;
328 return false;
329 }
330 wakeup_pipe_out_ = fds[0];
331 wakeup_pipe_in_ = fds[1];
332
333 wakeup_event_ = new event;
334 event_set(wakeup_event_, wakeup_pipe_out_, EV_READ | EV_PERSIST,
335 OnWakeup, this);
336 event_base_set(event_base_, wakeup_event_);
337
338 if (event_add(wakeup_event_, 0))
339 return false;
340 return true;
341}
342
343// static
344void MessagePumpLibevent::OnLibeventNotification(int fd, short flags,
345 void* context) {
[email protected]8d5f3ac2011-07-20 16:01:32346 base::WeakPtr<FileDescriptorWatcher> controller =
347 static_cast<FileDescriptorWatcher*>(context)->weak_factory_.GetWeakPtr();
348 DCHECK(controller.get());
[email protected]eae9c062011-01-11 00:50:59349
350 MessagePumpLibevent* pump = controller->pump();
[email protected]4b4a94f22b2011-07-01 01:55:29351 pump->processed_io_events_ = true;
[email protected]eae9c062011-01-11 00:50:59352
353 if (flags & EV_WRITE) {
354 controller->OnFileCanWriteWithoutBlocking(fd, pump);
355 }
[email protected]e4d70962011-07-21 20:16:11356 // Check |controller| in case it's been deleted in
357 // controller->OnFileCanWriteWithoutBlocking().
[email protected]8d5f3ac2011-07-20 16:01:32358 if (controller.get() && flags & EV_READ) {
[email protected]eae9c062011-01-11 00:50:59359 controller->OnFileCanReadWithoutBlocking(fd, pump);
360 }
361}
362
363// Called if a byte is received on the wakeup pipe.
364// static
365void MessagePumpLibevent::OnWakeup(int socket, short flags, void* context) {
366 base::MessagePumpLibevent* that =
367 static_cast<base::MessagePumpLibevent*>(context);
368 DCHECK(that->wakeup_pipe_out_ == socket);
369
370 // Remove and discard the wakeup byte.
371 char buf;
372 int nread = HANDLE_EINTR(read(socket, &buf, 1));
373 DCHECK_EQ(nread, 1);
[email protected]4b4a94f22b2011-07-01 01:55:29374 that->processed_io_events_ = true;
[email protected]eae9c062011-01-11 00:50:59375 // Tell libevent to break out of inner loop.
376 event_base_loopbreak(that->event_base_);
377}
378
[email protected]36987e92008-09-18 18:46:26379} // namespace base