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

Side by Side Diff: runtime/bin/eventhandler_macos.cc

Issue 2635253002: VM eventhandler: Read "old" event mask before it can be modified. (Closed)
Patch Set: Created 3 years, 11 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
« no previous file with comments | « runtime/bin/eventhandler_macos.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) 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
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
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
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
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
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)
OLDNEW
« no previous file with comments | « runtime/bin/eventhandler_macos.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698