OLD | NEW |
---|---|
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 #if !defined(DART_IO_DISABLED) | 5 #if !defined(DART_IO_DISABLED) |
6 | 6 |
7 #include "platform/globals.h" | 7 #include "platform/globals.h" |
8 #if defined(TARGET_OS_MACOS) | 8 #if defined(TARGET_OS_MACOS) |
9 | 9 |
10 #include "bin/eventhandler.h" | 10 #include "bin/eventhandler.h" |
(...skipping 25 matching lines...) Expand all Loading... | |
36 } | 36 } |
37 | 37 |
38 | 38 |
39 bool DescriptorInfo::HasWriteEvent() { | 39 bool DescriptorInfo::HasWriteEvent() { |
40 return (Mask() & (1 << kOutEvent)) != 0; | 40 return (Mask() & (1 << kOutEvent)) != 0; |
41 } | 41 } |
42 | 42 |
43 | 43 |
44 // Unregister the file descriptor for a SocketData structure with kqueue. | 44 // Unregister the file descriptor for a SocketData structure with kqueue. |
45 static void RemoveFromKqueue(intptr_t kqueue_fd_, DescriptorInfo* di) { | 45 static void RemoveFromKqueue(intptr_t kqueue_fd_, DescriptorInfo* di) { |
46 if (!di->tracked_by_kqueue()) { | |
47 return; | |
48 } | |
49 static const intptr_t kMaxChanges = 2; | 46 static const intptr_t kMaxChanges = 2; |
50 struct kevent events[kMaxChanges]; | 47 struct kevent events[kMaxChanges]; |
kustermann
2017/01/20 12:22:49
Unrelated side note:
Seems like legacy code: We o
zra
2017/01/20 17:16:32
Maybe in another CL. We should try the bug fix in
| |
51 EV_SET(events, di->fd(), EVFILT_READ, EV_DELETE, 0, 0, NULL); | 48 EV_SET(events, di->fd(), EVFILT_READ, EV_DELETE, 0, 0, NULL); |
52 VOID_NO_RETRY_EXPECTED(kevent(kqueue_fd_, events, 1, NULL, 0, NULL)); | 49 VOID_NO_RETRY_EXPECTED(kevent(kqueue_fd_, events, 1, NULL, 0, NULL)); |
kustermann
2017/01/20 12:22:49
Unrelated side note:
We should probably check th
zra
2017/01/20 17:16:32
ditto
| |
53 EV_SET(events, di->fd(), EVFILT_WRITE, EV_DELETE, 0, 0, NULL); | 50 EV_SET(events, di->fd(), EVFILT_WRITE, EV_DELETE, 0, 0, NULL); |
54 VOID_NO_RETRY_EXPECTED(kevent(kqueue_fd_, events, 1, NULL, 0, NULL)); | 51 VOID_NO_RETRY_EXPECTED(kevent(kqueue_fd_, events, 1, NULL, 0, NULL)); |
kustermann
2017/01/20 12:22:49
Unrelated side note:
As opposed to the adding co
zra
2017/01/20 17:16:32
ditto
| |
55 di->set_tracked_by_kqueue(false); | |
56 } | 52 } |
57 | 53 |
58 | 54 |
59 // Update the kqueue registration for SocketData structure to reflect | 55 // Update the kqueue registration for SocketData structure to reflect |
60 // the events currently of interest. | 56 // the events currently of interest. |
61 static void AddToKqueue(intptr_t kqueue_fd_, DescriptorInfo* di) { | 57 static void AddToKqueue(intptr_t kqueue_fd_, DescriptorInfo* di) { |
62 ASSERT(!di->tracked_by_kqueue()); | |
kustermann
2017/01/20 12:22:49
I cannot think of a case where this ASSERT should
| |
63 static const intptr_t kMaxChanges = 2; | 58 static const intptr_t kMaxChanges = 2; |
64 intptr_t changes = 0; | 59 intptr_t changes = 0; |
65 struct kevent events[kMaxChanges]; | 60 struct kevent events[kMaxChanges]; |
66 int flags = EV_ADD; | 61 int flags = EV_ADD; |
67 if (!di->IsListeningSocket()) { | 62 if (!di->IsListeningSocket()) { |
68 flags |= EV_CLEAR; | 63 flags |= EV_CLEAR; |
69 } | 64 } |
70 | 65 |
71 ASSERT(di->HasReadEvent() || di->HasWriteEvent()); | 66 ASSERT(di->HasReadEvent() || di->HasWriteEvent()); |
72 | 67 |
(...skipping 12 matching lines...) Expand all Loading... | |
85 int status = | 80 int status = |
86 NO_RETRY_EXPECTED(kevent(kqueue_fd_, events, changes, NULL, 0, NULL)); | 81 NO_RETRY_EXPECTED(kevent(kqueue_fd_, events, changes, NULL, 0, NULL)); |
87 if (status == -1) { | 82 if (status == -1) { |
88 // TODO(dart:io): Verify that the dart end is handling this correctly. | 83 // TODO(dart:io): Verify that the dart end is handling this correctly. |
89 | 84 |
90 // kQueue does not accept the file descriptor. It could be due to | 85 // kQueue does not accept the file descriptor. It could be due to |
91 // already closed file descriptor, or unuspported devices, such | 86 // already closed file descriptor, or unuspported devices, such |
92 // as /dev/null. In such case, mark the file descriptor as closed, | 87 // as /dev/null. In such case, mark the file descriptor as closed, |
93 // so dart will handle it accordingly. | 88 // so dart will handle it accordingly. |
94 di->NotifyAllDartPorts(1 << kCloseEvent); | 89 di->NotifyAllDartPorts(1 << kCloseEvent); |
95 } else { | |
96 di->set_tracked_by_kqueue(true); | |
97 } | 90 } |
98 } | 91 } |
99 | 92 |
100 | 93 |
101 EventHandlerImplementation::EventHandlerImplementation() | 94 EventHandlerImplementation::EventHandlerImplementation() |
102 : socket_map_(&HashMap::SamePointerValue, 16) { | 95 : socket_map_(&HashMap::SamePointerValue, 16) { |
103 intptr_t result; | 96 intptr_t result; |
104 result = NO_RETRY_EXPECTED(pipe(interrupt_fds_)); | 97 result = NO_RETRY_EXPECTED(pipe(interrupt_fds_)); |
105 if (result != 0) { | 98 if (result != 0) { |
106 FATAL("Pipe creation failed"); | 99 FATAL("Pipe creation failed"); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
153 | 146 |
154 void EventHandlerImplementation::UpdateKQueueInstance(intptr_t old_mask, | 147 void EventHandlerImplementation::UpdateKQueueInstance(intptr_t old_mask, |
155 DescriptorInfo* di) { | 148 DescriptorInfo* di) { |
156 intptr_t new_mask = di->Mask(); | 149 intptr_t new_mask = di->Mask(); |
157 if (old_mask != 0 && new_mask == 0) { | 150 if (old_mask != 0 && new_mask == 0) { |
158 RemoveFromKqueue(kqueue_fd_, di); | 151 RemoveFromKqueue(kqueue_fd_, di); |
159 } else if ((old_mask == 0) && (new_mask != 0)) { | 152 } else if ((old_mask == 0) && (new_mask != 0)) { |
160 AddToKqueue(kqueue_fd_, di); | 153 AddToKqueue(kqueue_fd_, di); |
161 } else if ((old_mask != 0) && (new_mask != 0) && (old_mask != new_mask)) { | 154 } else if ((old_mask != 0) && (new_mask != 0) && (old_mask != new_mask)) { |
162 ASSERT(!di->IsListeningSocket()); | 155 ASSERT(!di->IsListeningSocket()); |
163 RemoveFromKqueue(kqueue_fd_, di); | 156 // kevent() will automatically replace the old filter for an existing fd. |
157 // There is no need to remove it first. | |
164 AddToKqueue(kqueue_fd_, di); | 158 AddToKqueue(kqueue_fd_, di); |
kustermann
2017/01/20 12:22:49
This is an incorrect change if I understand it pro
zra
2017/01/20 17:16:32
Acknowledged.
| |
165 } | 159 } |
166 } | 160 } |
167 | 161 |
168 | 162 |
169 DescriptorInfo* EventHandlerImplementation::GetDescriptorInfo( | 163 DescriptorInfo* EventHandlerImplementation::GetDescriptorInfo( |
170 intptr_t fd, | 164 intptr_t fd, |
171 bool is_listening) { | 165 bool is_listening) { |
172 ASSERT(fd >= 0); | 166 ASSERT(fd >= 0); |
173 HashMap::Entry* entry = socket_map_.Lookup(GetHashmapKeyFromFd(fd), | 167 HashMap::Entry* entry = socket_map_.Lookup(GetHashmapKeyFromFd(fd), |
174 GetHashmapHashFromFd(fd), true); | 168 GetHashmapHashFromFd(fd), true); |
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
381 if ((events[i].flags & EV_ERROR) != 0) { | 375 if ((events[i].flags & EV_ERROR) != 0) { |
382 const int kBufferSize = 1024; | 376 const int kBufferSize = 1024; |
383 char error_message[kBufferSize]; | 377 char error_message[kBufferSize]; |
384 Utils::StrError(events[i].data, error_message, kBufferSize); | 378 Utils::StrError(events[i].data, error_message, kBufferSize); |
385 FATAL1("kevent failed %s\n", error_message); | 379 FATAL1("kevent failed %s\n", error_message); |
386 } | 380 } |
387 if (events[i].udata == NULL) { | 381 if (events[i].udata == NULL) { |
388 interrupt_seen = true; | 382 interrupt_seen = true; |
389 } else { | 383 } else { |
390 DescriptorInfo* di = reinterpret_cast<DescriptorInfo*>(events[i].udata); | 384 DescriptorInfo* di = reinterpret_cast<DescriptorInfo*>(events[i].udata); |
391 intptr_t event_mask = GetEvents(events + i, di); | 385 intptr_t event_mask = GetEvents(events + i, di); |
kustermann
2017/01/20 12:22:49
Unrelated side note:
Suggestion: We could traver
| |
392 if ((event_mask & (1 << kErrorEvent)) != 0) { | 386 if ((event_mask & (1 << kErrorEvent)) != 0) { |
393 di->NotifyAllDartPorts(event_mask); | 387 di->NotifyAllDartPorts(event_mask); |
394 } | 388 } |
395 event_mask &= ~(1 << kErrorEvent); | 389 event_mask &= ~(1 << kErrorEvent); |
396 | 390 |
397 if (event_mask != 0) { | 391 if (event_mask != 0) { |
398 intptr_t old_mask = di->Mask(); | 392 intptr_t old_mask = di->Mask(); |
zra
2017/01/20 15:54:30
I'm pretty sure the problem is here.
If the event
kustermann
2017/01/23 11:49:34
Very good point.
| |
399 Dart_Port port = di->NextNotifyDartPort(event_mask); | 393 Dart_Port port = di->NextNotifyDartPort(event_mask); |
400 ASSERT(port != 0); | 394 ASSERT(port != 0); |
401 UpdateKQueueInstance(old_mask, di); | 395 UpdateKQueueInstance(old_mask, di); |
402 DartUtils::PostInt32(port, event_mask); | 396 DartUtils::PostInt32(port, event_mask); |
403 } | 397 } |
404 } | 398 } |
405 } | 399 } |
406 if (interrupt_seen) { | 400 if (interrupt_seen) { |
407 // Handle after socket events, so we avoid closing a socket before we handle | 401 // Handle after socket events, so we avoid closing a socket before we handle |
408 // the current events. | 402 // the current events. |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
506 // The hashmap does not support keys with value 0. | 500 // The hashmap does not support keys with value 0. |
507 return dart::Utils::WordHash(fd + 1); | 501 return dart::Utils::WordHash(fd + 1); |
508 } | 502 } |
509 | 503 |
510 } // namespace bin | 504 } // namespace bin |
511 } // namespace dart | 505 } // namespace dart |
512 | 506 |
513 #endif // defined(TARGET_OS_MACOS) | 507 #endif // defined(TARGET_OS_MACOS) |
514 | 508 |
515 #endif // !defined(DART_IO_DISABLED) | 509 #endif // !defined(DART_IO_DISABLED) |
OLD | NEW |