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

Side by Side Diff: dart/runtime/bin/eventhandler_android.cc

Issue 879353003: Introduce optional 'bool shared' parameter to ServerSocket.bind() ... (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge
Patch Set: Part 3: Other platforms (preliminary) Created 5 years, 10 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
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "platform/globals.h" 5 #include "platform/globals.h"
6 #if defined(TARGET_OS_ANDROID) 6 #if defined(TARGET_OS_ANDROID)
7 7
8 #include "bin/eventhandler.h" 8 #include "bin/eventhandler.h"
9 #include "bin/eventhandler_android.h"
9 10
10 #include <errno.h> // NOLINT 11 #include <errno.h> // NOLINT
11 #include <pthread.h> // NOLINT 12 #include <pthread.h> // NOLINT
12 #include <stdio.h> // NOLINT 13 #include <stdio.h> // NOLINT
13 #include <string.h> // NOLINT 14 #include <string.h> // NOLINT
14 #include <sys/epoll.h> // NOLINT 15 #include <sys/epoll.h> // NOLINT
15 #include <sys/stat.h> // NOLINT 16 #include <sys/stat.h> // NOLINT
16 #include <unistd.h> // NOLINT 17 #include <unistd.h> // NOLINT
17 #include <fcntl.h> // NOLINT 18 #include <fcntl.h> // NOLINT
18 19
19 #include "bin/dartutils.h" 20 #include "bin/dartutils.h"
20 #include "bin/fdutils.h" 21 #include "bin/fdutils.h"
21 #include "bin/log.h" 22 #include "bin/log.h"
23 #include "bin/lockers.h"
24 #include "bin/socket.h"
22 #include "bin/thread.h" 25 #include "bin/thread.h"
23 #include "bin/utils.h" 26 #include "bin/utils.h"
24 #include "platform/hashmap.h" 27 #include "platform/hashmap.h"
25 #include "platform/utils.h" 28 #include "platform/utils.h"
26 29
27 30
28 // Android doesn't define EPOLLRDHUP. 31 // Android doesn't define EPOLLRDHUP.
29 #if !defined(EPOLLRDHUP) 32 #if !defined(EPOLLRDHUP)
30 #define EPOLLRDHUP 0x2000 33 #define EPOLLRDHUP 0x2000
31 #endif // !defined(EPOLLRDHUP) 34 #endif // !defined(EPOLLRDHUP)
32 35
33 36
34 namespace dart { 37 namespace dart {
35 namespace bin { 38 namespace bin {
36 39
37 static const int kInterruptMessageSize = sizeof(InterruptMessage);
38 static const int kInfinityTimeout = -1;
39 static const int kTimerId = -1;
40 static const int kShutdownId = -2;
41 40
42 41 intptr_t DescriptorInfoAndroid::GetPollEvents() {
43 intptr_t SocketData::GetPollEvents() {
44 // Do not ask for EPOLLERR and EPOLLHUP explicitly as they are 42 // Do not ask for EPOLLERR and EPOLLHUP explicitly as they are
45 // triggered anyway. 43 // triggered anyway.
46 intptr_t events = 0; 44 intptr_t events = 0;
47 if ((mask_ & (1 << kInEvent)) != 0) { 45 if ((Mask() & (1 << kInEvent)) != 0) {
48 events |= EPOLLIN; 46 events |= EPOLLIN;
49 } 47 }
50 if ((mask_ & (1 << kOutEvent)) != 0) { 48 if ((Mask() & (1 << kOutEvent)) != 0) {
51 events |= EPOLLOUT; 49 events |= EPOLLOUT;
52 } 50 }
53 return events; 51 return events;
54 } 52 }
55 53
56 54
57 // Unregister the file descriptor for a SocketData structure with epoll. 55 // Unregister the file descriptor for a DescriptorInfoAndroid structure with
58 static void RemoveFromEpollInstance(intptr_t epoll_fd_, SocketData* sd) { 56 // epoll.
57 static void RemoveFromEpollInstance(intptr_t epoll_fd_,
58 DescriptorInfoAndroid* si) {
Søren Gjesse 2015/02/02 10:56:14 si -> di
kustermann 2015/02/03 10:45:35 Originally I called the class SocketInfo, but it's
59 VOID_NO_RETRY_EXPECTED(epoll_ctl(epoll_fd_, 59 VOID_NO_RETRY_EXPECTED(epoll_ctl(epoll_fd_,
60 EPOLL_CTL_DEL, 60 EPOLL_CTL_DEL,
61 sd->fd(), 61 si->fd(),
62 NULL)); 62 NULL));
63 } 63 }
64 64
65 65
66 static void AddToEpollInstance(intptr_t epoll_fd_, SocketData* sd) { 66 static void AddToEpollInstance(intptr_t epoll_fd_, SocketData* si) {
Søren Gjesse 2015/02/02 10:56:14 SocketData -> DescriptorInfo/DescriptorInfoAndroid
kustermann 2015/02/03 10:45:35 Done.
67 struct epoll_event event; 67 struct epoll_event event;
68 event.events = EPOLLRDHUP | sd->GetPollEvents(); 68 event.events = EPOLLRDHUP | si->GetPollEvents();
69 if (!sd->IsListeningSocket()) { 69 if (!si->IsListeningSocket()) {
70 event.events |= EPOLLET; 70 event.events |= EPOLLET;
71 } 71 }
72 event.data.ptr = sd; 72 event.data.ptr = si;
73 int status = NO_RETRY_EXPECTED(epoll_ctl(epoll_fd_, 73 int status = NO_RETRY_EXPECTED(epoll_ctl(epoll_fd_,
74 EPOLL_CTL_ADD, 74 EPOLL_CTL_ADD,
75 sd->fd(), 75 si->fd(),
76 &event)); 76 &event));
77 if (status == -1) { 77 if (status == -1) {
78 // Epoll does not accept the file descriptor. It could be due to 78 // Epoll does not accept the file descriptor. It could be due to
79 // already closed file descriptor, or unuspported devices, such 79 // already closed file descriptor, or unuspported devices, such
80 // as /dev/null. In such case, mark the file descriptor as closed, 80 // as /dev/null. In such case, mark the file descriptor as closed,
81 // so dart will handle it accordingly. 81 // so dart will handle it accordingly.
82 DartUtils::PostInt32(sd->port(), 1 << kCloseEvent); 82 DartUtils::PostInt32(si->NextPort(), 1 << kCloseEvent);
Søren Gjesse 2015/02/02 10:56:14 How will this work for listening sockets with mult
kustermann 2015/02/03 10:45:35 I don't know what happens if we send a close event
83 } 83 }
84 } 84 }
85 85
86 86
87 EventHandlerImplementation::EventHandlerImplementation() 87 EventHandlerImplementation::EventHandlerImplementation()
88 : socket_map_(&HashMap::SamePointerValue, 16) { 88 : socket_map_(&HashMap::SamePointerValue, 16) {
89 intptr_t result; 89 intptr_t result;
90 result = NO_RETRY_EXPECTED(pipe(interrupt_fds_)); 90 result = NO_RETRY_EXPECTED(pipe(interrupt_fds_));
91 if (result != 0) { 91 if (result != 0) {
92 FATAL("Pipe creation failed"); 92 FATAL("Pipe creation failed");
93 } 93 }
94 FDUtils::SetNonBlocking(interrupt_fds_[0]); 94 FDUtils::SetNonBlocking(interrupt_fds_[0]);
95 FDUtils::SetCloseOnExec(interrupt_fds_[0]); 95 FDUtils::SetCloseOnExec(interrupt_fds_[0]);
96 FDUtils::SetCloseOnExec(interrupt_fds_[1]); 96 FDUtils::SetCloseOnExec(interrupt_fds_[1]);
97 shutdown_ = false; 97 shutdown_ = false;
98 // The initial size passed to epoll_create is ignore on newer (>= 98 // The initial size passed to epoll_create is ignore on newer (>=
99 // 2.6.8) Linux versions 99 // 2.6.8) Linux versions
100 static const int kEpollInitialSize = 64; 100 static const int kEpollInitialSize = 64;
101 epoll_fd_ = NO_RETRY_EXPECTED(epoll_create(kEpollInitialSize)); 101 epoll_fd_ = NO_RETRY_EXPECTED(epoll_create(kEpollInitialSize));
102 if (epoll_fd_ == -1) { 102 if (epoll_fd_ == -1) {
103 FATAL("Failed creating epoll file descriptor"); 103 FATAL1("Failed creating epoll file descriptor: %i", errno);
104 } 104 }
105 FDUtils::SetCloseOnExec(epoll_fd_); 105 FDUtils::SetCloseOnExec(epoll_fd_);
106 // Register the interrupt_fd with the epoll instance. 106 // Register the interrupt_fd with the epoll instance.
107 struct epoll_event event; 107 struct epoll_event event;
108 event.events = EPOLLIN; 108 event.events = EPOLLIN;
109 event.data.ptr = NULL; 109 event.data.ptr = NULL;
110 int status = NO_RETRY_EXPECTED(epoll_ctl(epoll_fd_, 110 int status = NO_RETRY_EXPECTED(epoll_ctl(epoll_fd_,
111 EPOLL_CTL_ADD, 111 EPOLL_CTL_ADD,
112 interrupt_fds_[0], 112 interrupt_fds_[0],
113 &event)); 113 &event));
114 if (status == -1) { 114 if (status == -1) {
115 FATAL("Failed adding interrupt fd to epoll instance"); 115 FATAL("Failed adding interrupt fd to epoll instance");
116 } 116 }
117 } 117 }
118 118
119 119
120 EventHandlerImplementation::~EventHandlerImplementation() { 120 EventHandlerImplementation::~EventHandlerImplementation() {
121 VOID_TEMP_FAILURE_RETRY(close(epoll_fd_));
121 VOID_TEMP_FAILURE_RETRY(close(interrupt_fds_[0])); 122 VOID_TEMP_FAILURE_RETRY(close(interrupt_fds_[0]));
122 VOID_TEMP_FAILURE_RETRY(close(interrupt_fds_[1])); 123 VOID_TEMP_FAILURE_RETRY(close(interrupt_fds_[1]));
123 } 124 }
124 125
125 126
126 SocketData* EventHandlerImplementation::GetSocketData(intptr_t fd) { 127 DescriptorInfoAndroid* EventHandlerImplementation::GetDescriptorInfoAndroid(
128 intptr_t fd, bool is_listening) {
127 ASSERT(fd >= 0); 129 ASSERT(fd >= 0);
128 HashMap::Entry* entry = socket_map_.Lookup( 130 HashMap::Entry* entry = socket_map_.Lookup(
129 GetHashmapKeyFromFd(fd), GetHashmapHashFromFd(fd), true); 131 GetHashmapKeyFromFd(fd), GetHashmapHashFromFd(fd), true);
130 ASSERT(entry != NULL); 132 ASSERT(entry != NULL);
131 SocketData* sd = reinterpret_cast<SocketData*>(entry->value); 133 DescriptorInfoAndroid* si =
132 if (sd == NULL) { 134 reinterpret_cast<DescriptorInfoAndroid*>(entry->value);
135 if (si == NULL) {
133 // If there is no data in the hash map for this file descriptor a 136 // If there is no data in the hash map for this file descriptor a
134 // new SocketData for the file descriptor is inserted. 137 // new DescriptorInfoAndroid for the file descriptor is inserted.
135 sd = new SocketData(fd); 138 if (is_listening) {
136 entry->value = sd; 139 si = new DescriptorInfoMultipleAndroid(fd);
140 } else {
141 si = new DescriptorInfoSingleAndroid(fd);
142 }
143 entry->value = si;
137 } 144 }
138 ASSERT(fd == sd->fd()); 145 ASSERT(fd == si->fd());
139 return sd; 146 return si;
140 } 147 }
141 148
142 149
143 void EventHandlerImplementation::WakeupHandler(intptr_t id, 150 void EventHandlerImplementation::WakeupHandler(intptr_t id,
144 Dart_Port dart_port, 151 Dart_Port dart_port,
145 int64_t data) { 152 int64_t data) {
146 InterruptMessage msg; 153 InterruptMessage msg;
147 msg.id = id; 154 msg.id = id;
148 msg.dart_port = dart_port; 155 msg.dart_port = dart_port;
149 msg.data = data; 156 msg.data = data;
150 // WriteToBlocking will write up to 512 bytes atomically, and since our msg 157 // WriteToBlocking will write up to 512 bytes atomically, and since our msg
151 // is smaller than 512, we don't need a thread lock. 158 // is smaller than 512, we don't need a thread lock.
152 // See: http://linux.die.net/man/7/pipe, section 'Pipe_buf'. 159 // See: http://linux.die.net/man/7/pipe, section 'Pipe_buf'.
153 ASSERT(kInterruptMessageSize < PIPE_BUF); 160 ASSERT(kInterruptMessageSize < PIPE_BUF);
154 intptr_t result = 161 intptr_t result =
155 FDUtils::WriteToBlocking(interrupt_fds_[1], &msg, kInterruptMessageSize); 162 FDUtils::WriteToBlocking(interrupt_fds_[1], &msg, kInterruptMessageSize);
156 if (result != kInterruptMessageSize) { 163 if (result != kInterruptMessageSize) {
157 if (result == -1) { 164 if (result == -1) {
158 perror("Interrupt message failure:"); 165 perror("Interrupt message failure:");
159 } 166 }
160 FATAL1("Interrupt message failure. Wrote %d bytes.", result); 167 FATAL1("Interrupt message failure. Wrote %" Pd " bytes.", result);
161 } 168 }
162 } 169 }
163 170
164 171
165 void EventHandlerImplementation::HandleInterruptFd() { 172 void EventHandlerImplementation::HandleInterruptFd() {
166 const intptr_t MAX_MESSAGES = kInterruptMessageSize; 173 const intptr_t MAX_MESSAGES = kInterruptMessageSize;
167 InterruptMessage msg[MAX_MESSAGES]; 174 InterruptMessage msg[MAX_MESSAGES];
168 ssize_t bytes = TEMP_FAILURE_RETRY_NO_SIGNAL_BLOCKER( 175 ssize_t bytes = TEMP_FAILURE_RETRY_NO_SIGNAL_BLOCKER(
169 read(interrupt_fds_[0], msg, MAX_MESSAGES * kInterruptMessageSize)); 176 read(interrupt_fds_[0], msg, MAX_MESSAGES * kInterruptMessageSize));
170 for (ssize_t i = 0; i < bytes / kInterruptMessageSize; i++) { 177 for (ssize_t i = 0; i < bytes / kInterruptMessageSize; i++) {
171 if (msg[i].id == kTimerId) { 178 if (msg[i].id == kTimerId) {
172 timeout_queue_.UpdateTimeout(msg[i].dart_port, msg[i].data); 179 timeout_queue_.UpdateTimeout(msg[i].dart_port, msg[i].data);
173 } else if (msg[i].id == kShutdownId) { 180 } else if (msg[i].id == kShutdownId) {
174 shutdown_ = true; 181 shutdown_ = true;
175 } else { 182 } else {
176 SocketData* sd = GetSocketData(msg[i].id); 183 DescriptorInfoAndroid* si = GetDescriptorInfoAndroid(
184 msg[i].id, (msg[i].data & (1 << kListeningSocket)) != 0);
185 if (IS_COMMAND(msg[i].data, kShutdownReadCommand)) {
186 ASSERT(!si->IsListeningSocket());
187 // Close the socket for reading.
188 VOID_NO_RETRY_EXPECTED(shutdown(si->fd(), SHUT_RD));
189 } else if (IS_COMMAND(msg[i].data, kShutdownWriteCommand)) {
190 ASSERT(!si->IsListeningSocket());
191 // Close the socket for writing.
192 VOID_NO_RETRY_EXPECTED(shutdown(si->fd(), SHUT_WR));
193 } else if (IS_COMMAND(msg[i].data, kCloseCommand)) {
194 // Close the socket and free system resources and move on to next
195 // message.
196 bool no_more_listeners = si->RemovePort(msg[i].dart_port);
197 if (no_more_listeners) {
198 RemoveFromEpollInstance(epoll_fd_, si);
199 }
177 200
178 if (IS_COMMAND(msg[i].data, kShutdownReadCommand)) { 201 if (si->IsListeningSocket()) {
179 // Close the socket for reading. 202 intptr_t fd = si->fd();
180 shutdown(sd->fd(), SHUT_RD); 203 // We only close the socket file descriptor from the operating
181 } else if (IS_COMMAND(msg[i].data, kShutdownWriteCommand)) { 204 // system if there are no other dart socket objects which
182 // Close the socket for writing. 205 // are listening on the same (address, port) combination.
183 shutdown(sd->fd(), SHUT_WR); 206 {
184 } else if (IS_COMMAND(msg[i].data, kCloseCommand)) { 207 MutexLocker ml(globalTcpListeningSocketRegistry.mutex());
185 // Close the socket and free system resources and move on to 208 if (globalTcpListeningSocketRegistry.CloseSafe(si->fd())) {
186 // next message. 209 ASSERT(no_more_listeners);
187 RemoveFromEpollInstance(epoll_fd_, sd); 210 socket_map_.Remove(
188 intptr_t fd = sd->fd(); 211 GetHashmapKeyFromFd(fd), GetHashmapHashFromFd(fd));
189 sd->Close(); 212 si->Close();
190 socket_map_.Remove(GetHashmapKeyFromFd(fd), GetHashmapHashFromFd(fd)); 213 delete si;
191 delete sd; 214 }
215 }
216 } else {
217 if (no_more_listeners) {
Søren Gjesse 2015/02/02 10:56:14 Isn't this always true for a non-listening socket?
kustermann 2015/02/03 10:45:35 Done.
218 intptr_t fd = si->fd();
219 socket_map_.Remove(
220 GetHashmapKeyFromFd(fd), GetHashmapHashFromFd(fd));
221 si->Close();
222 delete si;
223 }
224 }
192 DartUtils::PostInt32(msg[i].dart_port, 1 << kDestroyedEvent); 225 DartUtils::PostInt32(msg[i].dart_port, 1 << kDestroyedEvent);
193 } else if (IS_COMMAND(msg[i].data, kReturnTokenCommand)) { 226 } else if (IS_COMMAND(msg[i].data, kReturnTokenCommand)) {
194 int count = TOKEN_COUNT(msg[i].data); 227 int count = TOKEN_COUNT(msg[i].data);
195 228 if (si->ReturnTokens(msg[i].dart_port, count)) {
196 for (int i = 0; i < count; i++) { 229 AddToEpollInstance(epoll_fd_, si);
197 if (sd->ReturnToken()) {
198 AddToEpollInstance(epoll_fd_, sd);
199 }
200 } 230 }
201 } else { 231 } else {
202 ASSERT_NO_COMMAND(msg[i].data); 232 ASSERT_NO_COMMAND(msg[i].data);
203 // Setup events to wait for. 233 // Setup events to wait for.
204 sd->SetPortAndMask(msg[i].dart_port, msg[i].data); 234 if (si->AddPort(msg[i].dart_port)) {
205 AddToEpollInstance(epoll_fd_, sd); 235 si->SetMask(msg[i].data);
236 AddToEpollInstance(epoll_fd_, si);
237 }
206 } 238 }
207 } 239 }
208 } 240 }
209 } 241 }
210 242
211 #ifdef DEBUG_POLL 243 #ifdef DEBUG_POLL
212 static void PrintEventMask(intptr_t fd, intptr_t events) { 244 static void PrintEventMask(intptr_t fd, intptr_t events) {
213 Log::Print("%d ", fd); 245 Log::Print("%d ", fd);
214 if ((events & EPOLLIN) != 0) Log::Print("EPOLLIN "); 246 if ((events & EPOLLIN) != 0) Log::Print("EPOLLIN ");
215 if ((events & EPOLLPRI) != 0) Log::Print("EPOLLPRI "); 247 if ((events & EPOLLPRI) != 0) Log::Print("EPOLLPRI ");
216 if ((events & EPOLLOUT) != 0) Log::Print("EPOLLOUT "); 248 if ((events & EPOLLOUT) != 0) Log::Print("EPOLLOUT ");
217 if ((events & EPOLLERR) != 0) Log::Print("EPOLLERR "); 249 if ((events & EPOLLERR) != 0) Log::Print("EPOLLERR ");
218 if ((events & EPOLLHUP) != 0) Log::Print("EPOLLHUP "); 250 if ((events & EPOLLHUP) != 0) Log::Print("EPOLLHUP ");
219 if ((events & EPOLLRDHUP) != 0) Log::Print("EPOLLRDHUP "); 251 if ((events & EPOLLRDHUP) != 0) Log::Print("EPOLLRDHUP ");
220 int all_events = EPOLLIN | EPOLLPRI | EPOLLOUT | 252 int all_events = EPOLLIN | EPOLLPRI | EPOLLOUT |
221 EPOLLERR | EPOLLHUP | EPOLLRDHUP; 253 EPOLLERR | EPOLLHUP | EPOLLRDHUP;
222 if ((events & ~all_events) != 0) { 254 if ((events & ~all_events) != 0) {
223 Log::Print("(and %08x) ", events & ~all_events); 255 Log::Print("(and %08x) ", events & ~all_events);
224 } 256 }
225 Log::Print("(available %d) ", FDUtils::AvailableBytes(fd)); 257 Log::Print("(available %d) ", FDUtils::AvailableBytes(fd));
226 258
227 Log::Print("\n"); 259 Log::Print("\n");
228 } 260 }
229 #endif 261 #endif
230 262
231 intptr_t EventHandlerImplementation::GetPollEvents(intptr_t events, 263 intptr_t EventHandlerImplementation::GetPollEvents(intptr_t events,
232 SocketData* sd) { 264 DescriptorInfoAndroid* si) {
233 #ifdef DEBUG_POLL 265 #ifdef DEBUG_POLL
234 PrintEventMask(sd->fd(), events); 266 PrintEventMask(si->fd(), events);
235 #endif 267 #endif
236 if (events & EPOLLERR) { 268 if (events & EPOLLERR) {
237 // Return error only if EPOLLIN is present. 269 // Return error only if EPOLLIN is present.
238 return (events & EPOLLIN) ? (1 << kErrorEvent) : 0; 270 return (events & EPOLLIN) ? (1 << kErrorEvent) : 0;
239 } 271 }
240 intptr_t event_mask = 0; 272 intptr_t event_mask = 0;
241 if (events & EPOLLIN) event_mask |= (1 << kInEvent); 273 if (events & EPOLLIN) event_mask |= (1 << kInEvent);
242 if (events & EPOLLOUT) event_mask |= (1 << kOutEvent); 274 if (events & EPOLLOUT) event_mask |= (1 << kOutEvent);
243 if (events & (EPOLLHUP | EPOLLRDHUP)) event_mask |= (1 << kCloseEvent); 275 if (events & (EPOLLHUP | EPOLLRDHUP)) event_mask |= (1 << kCloseEvent);
244 return event_mask; 276 return event_mask;
245 } 277 }
246 278
247 279
248 void EventHandlerImplementation::HandleEvents(struct epoll_event* events, 280 void EventHandlerImplementation::HandleEvents(struct epoll_event* events,
249 int size) { 281 int size) {
250 bool interrupt_seen = false; 282 bool interrupt_seen = false;
251 for (int i = 0; i < size; i++) { 283 for (int i = 0; i < size; i++) {
252 if (events[i].data.ptr == NULL) { 284 if (events[i].data.ptr == NULL) {
253 interrupt_seen = true; 285 interrupt_seen = true;
254 } else { 286 } else {
255 SocketData* sd = reinterpret_cast<SocketData*>(events[i].data.ptr); 287 DescriptorInfoAndroid* si =
256 intptr_t event_mask = GetPollEvents(events[i].events, sd); 288 reinterpret_cast<DescriptorInfoAndroid*>(events[i].data.ptr);
289 intptr_t event_mask = GetPollEvents(events[i].events, si);
257 if (event_mask != 0) { 290 if (event_mask != 0) {
258 if (sd->TakeToken()) { 291 Dart_Port port = si->NextPort();
292 ASSERT(port != 0);
293 if (si->TakeToken()) {
259 // Took last token, remove from epoll. 294 // Took last token, remove from epoll.
260 RemoveFromEpollInstance(epoll_fd_, sd); 295 RemoveFromEpollInstance(epoll_fd_, si);
261 } 296 }
262 Dart_Port port = sd->port();
263 ASSERT(port != 0);
264 DartUtils::PostInt32(port, event_mask); 297 DartUtils::PostInt32(port, event_mask);
265 } 298 }
266 } 299 }
267 } 300 }
268 if (interrupt_seen) { 301 if (interrupt_seen) {
269 // Handle after socket events, so we avoid closing a socket before we handle 302 // Handle after socket events, so we avoid closing a socket before we handle
270 // the current events. 303 // the current events.
271 HandleInterruptFd(); 304 HandleInterruptFd();
272 } 305 }
273 } 306 }
(...skipping 18 matching lines...) Expand all
292 timeout_queue_.RemoveCurrent(); 325 timeout_queue_.RemoveCurrent();
293 } 326 }
294 } 327 }
295 } 328 }
296 329
297 330
298 void EventHandlerImplementation::Poll(uword args) { 331 void EventHandlerImplementation::Poll(uword args) {
299 ThreadSignalBlocker signal_blocker(SIGPROF); 332 ThreadSignalBlocker signal_blocker(SIGPROF);
300 static const intptr_t kMaxEvents = 16; 333 static const intptr_t kMaxEvents = 16;
301 struct epoll_event events[kMaxEvents]; 334 struct epoll_event events[kMaxEvents];
302 EventHandlerImplementation* handler = 335 EventHandler* handler = reinterpret_cast<EventHandler*>(args);
303 reinterpret_cast<EventHandlerImplementation*>(args); 336 EventHandlerImplementation* handler_impl = &handler->delegate_;
304 ASSERT(handler != NULL); 337 ASSERT(handler_impl != NULL);
305 while (!handler->shutdown_) { 338 while (!handler_impl->shutdown_) {
306 int64_t millis = handler->GetTimeout(); 339 int64_t millis = handler->GetTimeout();
307 ASSERT(millis == kInfinityTimeout || millis >= 0); 340 ASSERT(millis == kInfinityTimeout || millis >= 0);
308 if (millis > kMaxInt32) millis = kMaxInt32; 341 if (millis > kMaxInt32) millis = kMaxInt32;
309 intptr_t result = TEMP_FAILURE_RETRY_NO_SIGNAL_BLOCKER( 342 intptr_t result = TEMP_FAILURE_RETRY_NO_SIGNAL_BLOCKER(
310 epoll_wait(handler->epoll_fd_, events, kMaxEvents, millis)); 343 epoll_wait(handler_impl->epoll_fd_, events, kMaxEvents, millis));
311 ASSERT(EAGAIN == EWOULDBLOCK); 344 ASSERT(EAGAIN == EWOULDBLOCK);
312 if (result == -1) { 345 if (result == -1) {
313 if (errno != EWOULDBLOCK) { 346 if (errno != EWOULDBLOCK) {
314 perror("Poll failed"); 347 perror("Poll failed");
315 } 348 }
316 } else { 349 } else {
317 handler->HandleTimeout(); 350 handler->HandleTimeout();
318 handler->HandleEvents(events, result); 351 handler->HandleEvents(events, result);
319 } 352 }
320 } 353 }
354 delete handler;
321 } 355 }
322 356
323 357
324 void EventHandlerImplementation::Start(EventHandler* handler) { 358 void EventHandlerImplementation::Start(EventHandler* handler) {
325 int result = Thread::Start(&EventHandlerImplementation::Poll, 359 int result = Thread::Start(&EventHandlerImplementation::Poll,
326 reinterpret_cast<uword>(handler)); 360 reinterpret_cast<uword>(handler));
327 if (result != 0) { 361 if (result != 0) {
328 FATAL1("Failed to start event handler thread %d", result); 362 FATAL1("Failed to start event handler thread %d", result);
329 } 363 }
330 } 364 }
331 365
332 366
333 void EventHandlerImplementation::Shutdown() { 367 void EventHandlerImplementation::Shutdown() {
334 SendData(kShutdownId, 0, 0); 368 SendData(kShutdownId, 0, 0);
335 } 369 }
336 370
337 371
338 void EventHandlerImplementation::SendData(intptr_t id, 372 void EventHandlerImplementation::SendData(intptr_t id,
339 Dart_Port dart_port, 373 Dart_Port dart_port,
340 intptr_t data) { 374 int64_t data) {
341 WakeupHandler(id, dart_port, data); 375 WakeupHandler(id, dart_port, data);
342 } 376 }
343 377
344 378
345 void* EventHandlerImplementation::GetHashmapKeyFromFd(intptr_t fd) { 379 void* EventHandlerImplementation::GetHashmapKeyFromFd(intptr_t fd) {
346 // The hashmap does not support keys with value 0. 380 // The hashmap does not support keys with value 0.
347 return reinterpret_cast<void*>(fd + 1); 381 return reinterpret_cast<void*>(fd + 1);
348 } 382 }
349 383
350 384
351 uint32_t EventHandlerImplementation::GetHashmapHashFromFd(intptr_t fd) { 385 uint32_t EventHandlerImplementation::GetHashmapHashFromFd(intptr_t fd) {
352 // The hashmap does not support keys with value 0. 386 // The hashmap does not support keys with value 0.
353 return dart::Utils::WordHash(fd + 1); 387 return dart::Utils::WordHash(fd + 1);
354 } 388 }
355 389
356 } // namespace bin 390 } // namespace bin
357 } // namespace dart 391 } // namespace dart
358 392
359 #endif // defined(TARGET_OS_ANDROID) 393 #endif // defined(TARGET_OS_ANDROID)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698