OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/message_loop/message_pump_libevent.h" | 5 #include "base/message_loop/message_pump_libevent.h" |
6 | 6 |
7 #include <errno.h> | 7 #include <errno.h> |
8 #include <fcntl.h> | 8 #include <fcntl.h> |
9 #include <unistd.h> | 9 #include <unistd.h> |
10 | 10 |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
48 int flags = fcntl(fd, F_GETFL, 0); | 48 int flags = fcntl(fd, F_GETFL, 0); |
49 if (flags == -1) | 49 if (flags == -1) |
50 flags = 0; | 50 flags = 0; |
51 return fcntl(fd, F_SETFL, flags | O_NONBLOCK); | 51 return fcntl(fd, F_SETFL, flags | O_NONBLOCK); |
52 } | 52 } |
53 | 53 |
54 MessagePumpLibevent::FileDescriptorWatcher::FileDescriptorWatcher() | 54 MessagePumpLibevent::FileDescriptorWatcher::FileDescriptorWatcher() |
55 : event_(NULL), | 55 : event_(NULL), |
56 pump_(NULL), | 56 pump_(NULL), |
57 watcher_(NULL), | 57 watcher_(NULL), |
58 weak_factory_(this) { | 58 was_destroyed_(NULL) { |
59 } | 59 } |
60 | 60 |
61 MessagePumpLibevent::FileDescriptorWatcher::~FileDescriptorWatcher() { | 61 MessagePumpLibevent::FileDescriptorWatcher::~FileDescriptorWatcher() { |
62 if (event_) { | 62 if (event_) { |
63 StopWatchingFileDescriptor(); | 63 StopWatchingFileDescriptor(); |
64 } | 64 } |
| 65 if (was_destroyed_) { |
| 66 DCHECK(!*was_destroyed_); |
| 67 *was_destroyed_ = true; |
| 68 } |
65 } | 69 } |
66 | 70 |
67 bool MessagePumpLibevent::FileDescriptorWatcher::StopWatchingFileDescriptor() { | 71 bool MessagePumpLibevent::FileDescriptorWatcher::StopWatchingFileDescriptor() { |
68 event* e = ReleaseEvent(); | 72 event* e = ReleaseEvent(); |
69 if (e == NULL) | 73 if (e == NULL) |
70 return true; | 74 return true; |
71 | 75 |
72 // event_del() is a no-op if the event isn't active. | 76 // event_del() is a no-op if the event isn't active. |
73 int rv = event_del(e); | 77 int rv = event_del(e); |
74 delete e; | 78 delete e; |
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
333 event_set(wakeup_event_, wakeup_pipe_out_, EV_READ | EV_PERSIST, | 337 event_set(wakeup_event_, wakeup_pipe_out_, EV_READ | EV_PERSIST, |
334 OnWakeup, this); | 338 OnWakeup, this); |
335 event_base_set(event_base_, wakeup_event_); | 339 event_base_set(event_base_, wakeup_event_); |
336 | 340 |
337 if (event_add(wakeup_event_, 0)) | 341 if (event_add(wakeup_event_, 0)) |
338 return false; | 342 return false; |
339 return true; | 343 return true; |
340 } | 344 } |
341 | 345 |
342 // static | 346 // static |
343 void MessagePumpLibevent::OnLibeventNotification(int fd, short flags, | 347 void MessagePumpLibevent::OnLibeventNotification(int fd, |
| 348 short flags, |
344 void* context) { | 349 void* context) { |
345 WeakPtr<FileDescriptorWatcher> controller = | 350 FileDescriptorWatcher* controller = |
346 static_cast<FileDescriptorWatcher*>(context)->weak_factory_.GetWeakPtr(); | 351 static_cast<FileDescriptorWatcher*>(context); |
347 DCHECK(controller.get()); | 352 DCHECK(controller); |
348 TRACE_EVENT1("toplevel", "MessagePumpLibevent::OnLibeventNotification", | 353 TRACE_EVENT1("toplevel", "MessagePumpLibevent::OnLibeventNotification", |
349 "fd", fd); | 354 "fd", fd); |
350 | 355 |
351 MessagePumpLibevent* pump = controller->pump(); | 356 MessagePumpLibevent* pump = controller->pump(); |
352 pump->processed_io_events_ = true; | 357 pump->processed_io_events_ = true; |
353 | 358 |
354 if (flags & EV_WRITE) { | 359 if ((flags & (EV_READ | EV_WRITE)) == (EV_READ | EV_WRITE)) { |
| 360 // Both callbacks will be called. It is necessary to check that |controller| |
| 361 // is not destroyed. |
| 362 bool controller_was_destroyed = false; |
| 363 controller->was_destroyed_ = &controller_was_destroyed; |
355 controller->OnFileCanWriteWithoutBlocking(fd, pump); | 364 controller->OnFileCanWriteWithoutBlocking(fd, pump); |
356 } | 365 if (!controller_was_destroyed) |
357 // Check |controller| in case it's been deleted in | 366 controller->OnFileCanReadWithoutBlocking(fd, pump); |
358 // controller->OnFileCanWriteWithoutBlocking(). | 367 if (!controller_was_destroyed) |
359 if (controller.get() && flags & EV_READ) { | 368 controller->was_destroyed_ = nullptr; |
| 369 } else if (flags & EV_WRITE) { |
| 370 controller->OnFileCanWriteWithoutBlocking(fd, pump); |
| 371 } else if (flags & EV_READ) { |
360 controller->OnFileCanReadWithoutBlocking(fd, pump); | 372 controller->OnFileCanReadWithoutBlocking(fd, pump); |
361 } | 373 } |
362 } | 374 } |
363 | 375 |
364 // Called if a byte is received on the wakeup pipe. | 376 // Called if a byte is received on the wakeup pipe. |
365 // static | 377 // static |
366 void MessagePumpLibevent::OnWakeup(int socket, short flags, void* context) { | 378 void MessagePumpLibevent::OnWakeup(int socket, short flags, void* context) { |
367 MessagePumpLibevent* that = static_cast<MessagePumpLibevent*>(context); | 379 MessagePumpLibevent* that = static_cast<MessagePumpLibevent*>(context); |
368 DCHECK(that->wakeup_pipe_out_ == socket); | 380 DCHECK(that->wakeup_pipe_out_ == socket); |
369 | 381 |
370 // Remove and discard the wakeup byte. | 382 // Remove and discard the wakeup byte. |
371 char buf; | 383 char buf; |
372 int nread = HANDLE_EINTR(read(socket, &buf, 1)); | 384 int nread = HANDLE_EINTR(read(socket, &buf, 1)); |
373 DCHECK_EQ(nread, 1); | 385 DCHECK_EQ(nread, 1); |
374 that->processed_io_events_ = true; | 386 that->processed_io_events_ = true; |
375 // Tell libevent to break out of inner loop. | 387 // Tell libevent to break out of inner loop. |
376 event_base_loopbreak(that->event_base_); | 388 event_base_loopbreak(that->event_base_); |
377 } | 389 } |
378 | 390 |
379 } // namespace base | 391 } // namespace base |
OLD | NEW |