Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(39)

Side by Side Diff: base/message_pump_libevent.cc

Issue 87045: Plug hole in struct event lifecycle; should fix bug 10503 (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « base/message_pump_libevent.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2008 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2008 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_pump_libevent.h" 5 #include "base/message_pump_libevent.h"
6 6
7 #include <errno.h> 7 #include <errno.h>
8 #include <fcntl.h> 8 #include <fcntl.h>
9 9
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "base/scoped_nsautorelease_pool.h" 11 #include "base/scoped_nsautorelease_pool.h"
12 #include "base/scoped_ptr.h"
12 #include "base/time.h" 13 #include "base/time.h"
13 #include "third_party/libevent/event.h" 14 #include "third_party/libevent/event.h"
14 15
16 // Lifecycle of struct event
17 // Libevent uses two main data structures:
18 // struct event_base (of which there is one per message pump), and
19 // struct event (of which there is roughly one per socket).
20 // The socket's struct event is created in
21 // MessagePumpLibevent::WatchFileDescriptor(),
22 // is owned by the FileDescriptorWatcher, and is destroyed in
23 // StopWatchingFileDescriptor().
24 // It is moved into and out of lists in struct event_base by
25 // the libevent functions event_add() and event_del().
26 //
27 // TODO(dkegel):
28 // At the moment bad things happen if a FileDescriptorWatcher
29 // is active after its MessagePumpLibevent has been destroyed.
30 // See MessageLoopTest.FileDescriptorWatcherOutlivesMessageLoop
31 // Not clear yet whether that situation occurs in practice,
32 // but if it does, we need to fix it.
33
15 namespace base { 34 namespace base {
16 35
17 // Return 0 on success 36 // Return 0 on success
18 // Too small a function to bother putting in a library? 37 // Too small a function to bother putting in a library?
19 static int SetNonBlocking(int fd) { 38 static int SetNonBlocking(int fd) {
20 int flags = fcntl(fd, F_GETFL, 0); 39 int flags = fcntl(fd, F_GETFL, 0);
21 if (flags == -1) 40 if (flags == -1)
22 flags = 0; 41 flags = 0;
23 return fcntl(fd, F_SETFL, flags | O_NONBLOCK); 42 return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
24 } 43 }
25 44
26 MessagePumpLibevent::FileDescriptorWatcher::FileDescriptorWatcher() 45 MessagePumpLibevent::FileDescriptorWatcher::FileDescriptorWatcher()
27 : is_persistent_(false), 46 : is_persistent_(false),
28 event_(NULL) { 47 event_(NULL) {
29 } 48 }
30 49
31 MessagePumpLibevent::FileDescriptorWatcher::~FileDescriptorWatcher() { 50 MessagePumpLibevent::FileDescriptorWatcher::~FileDescriptorWatcher() {
32 if (event_.get()) { 51 if (event_) {
33 StopWatchingFileDescriptor(); 52 StopWatchingFileDescriptor();
34 } 53 }
35 } 54 }
36 55
37 void MessagePumpLibevent::FileDescriptorWatcher::Init(event *e, 56 void MessagePumpLibevent::FileDescriptorWatcher::Init(event *e,
38 bool is_persistent) { 57 bool is_persistent) {
39 DCHECK(e); 58 DCHECK(e);
40 DCHECK(event_.get() == NULL); 59 DCHECK(event_ == NULL);
41 60
42 is_persistent_ = is_persistent; 61 is_persistent_ = is_persistent;
43 event_.reset(e); 62 event_ = e;
44 } 63 }
45 64
46 event *MessagePumpLibevent::FileDescriptorWatcher::ReleaseEvent() { 65 event *MessagePumpLibevent::FileDescriptorWatcher::ReleaseEvent() {
47 return event_.release(); 66 struct event *e = event_;
67 event_ = NULL;
68 return e;
48 } 69 }
49 70
50 bool MessagePumpLibevent::FileDescriptorWatcher::StopWatchingFileDescriptor() { 71 bool MessagePumpLibevent::FileDescriptorWatcher::StopWatchingFileDescriptor() {
51 if (event_.get() == NULL) { 72 event* e = ReleaseEvent();
73 if (e == NULL)
52 return true; 74 return true;
53 }
54 75
55 // event_del() is a no-op of the event isn't active. 76 // event_del() is a no-op if the event isn't active.
56 return (event_del(event_.get()) == 0); 77 int rv = event_del(e);
78 delete e;
79 return (rv == 0);
57 } 80 }
58 81
59 // Called if a byte is received on the wakeup pipe. 82 // Called if a byte is received on the wakeup pipe.
60 void MessagePumpLibevent::OnWakeup(int socket, short flags, void* context) { 83 void MessagePumpLibevent::OnWakeup(int socket, short flags, void* context) {
61 base::MessagePumpLibevent* that = 84 base::MessagePumpLibevent* that =
62 static_cast<base::MessagePumpLibevent*>(context); 85 static_cast<base::MessagePumpLibevent*>(context);
63 DCHECK(that->wakeup_pipe_out_ == socket); 86 DCHECK(that->wakeup_pipe_out_ == socket);
64 87
65 // Remove and discard the wakeup byte. 88 // Remove and discard the wakeup byte.
66 char buf; 89 char buf;
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
162 } 185 }
163 186
164 // Add this socket to the list of monitored sockets. 187 // Add this socket to the list of monitored sockets.
165 if (event_add(evt.get(), NULL) != 0) { 188 if (event_add(evt.get(), NULL) != 0) {
166 if (should_delete_event) { 189 if (should_delete_event) {
167 event_del(evt.get()); 190 event_del(evt.get());
168 } 191 }
169 return false; 192 return false;
170 } 193 }
171 194
172 // Transfer ownership of e to controller. 195 // Transfer ownership of evt to controller.
173 controller->Init(evt.release(), persistent); 196 controller->Init(evt.release(), persistent);
174 return true; 197 return true;
175 } 198 }
176 199
177 200
178 void MessagePumpLibevent::OnLibeventNotification(int fd, short flags, 201 void MessagePumpLibevent::OnLibeventNotification(int fd, short flags,
179 void* context) { 202 void* context) {
180 Watcher* watcher = static_cast<Watcher*>(context); 203 Watcher* watcher = static_cast<Watcher*>(context);
181 204
182 if (flags & EV_WRITE) { 205 if (flags & EV_WRITE) {
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
255 } 278 }
256 279
257 void MessagePumpLibevent::ScheduleDelayedWork(const Time& delayed_work_time) { 280 void MessagePumpLibevent::ScheduleDelayedWork(const Time& delayed_work_time) {
258 // We know that we can't be blocked on Wait right now since this method can 281 // We know that we can't be blocked on Wait right now since this method can
259 // only be called on the same thread as Run, so we only need to update our 282 // only be called on the same thread as Run, so we only need to update our
260 // record of how long to sleep when we do sleep. 283 // record of how long to sleep when we do sleep.
261 delayed_work_time_ = delayed_work_time; 284 delayed_work_time_ = delayed_work_time;
262 } 285 }
263 286
264 } // namespace base 287 } // namespace base
OLDNEW
« no previous file with comments | « base/message_pump_libevent.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698