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

Unified Diff: runtime/bin/eventhandler_macos.cc

Issue 8437090: Change the handling of closing sockets (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Addressed review comments by ager@ Created 9 years, 1 month 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/bin/eventhandler_macos.h ('k') | runtime/bin/eventhandler_win.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/bin/eventhandler_macos.cc
diff --git a/runtime/bin/eventhandler_macos.cc b/runtime/bin/eventhandler_macos.cc
index eea6fca77b9d42d35c2a0b24672db0469fc0ba68..9764ac28484892ff52b602c15f273648b9152df3 100644
--- a/runtime/bin/eventhandler_macos.cc
+++ b/runtime/bin/eventhandler_macos.cc
@@ -24,29 +24,33 @@ int64_t GetCurrentTimeMilliseconds() {
}
-static const int kInitialPortMapSize = 128;
+static const int kInitialPortMapSize = 16;
static const int kPortMapGrowingFactor = 2;
static const int kInterruptMessageSize = sizeof(InterruptMessage);
static const int kInfinityTimeout = -1;
static const int kTimerId = -1;
-
-void SocketData::FillPollEvents(struct pollfd* pollfds) {
+intptr_t SocketData::GetPollEvents() {
// Do not ask for POLLERR and POLLHUP explicitly as they are
// triggered anyway.
- if ((_mask & (1 << kInEvent)) != 0) {
- pollfds->events |= POLLIN;
+ intptr_t events = 0;
+ if (!IsClosedRead()) {
+ if ((mask_ & (1 << kInEvent)) != 0) {
+ events |= POLLIN;
+ }
}
- if ((_mask & (1 << kOutEvent)) != 0) {
- pollfds->events |= POLLOUT;
+ if (!IsClosedWrite()) {
+ if ((mask_ & (1 << kOutEvent)) != 0) {
+ events |= POLLOUT;
+ }
}
+ return events;
}
EventHandlerImplementation::EventHandlerImplementation() {
intptr_t result;
- socket_map_entries_ = 0;
socket_map_size_ = kInitialPortMapSize;
socket_map_ = reinterpret_cast<SocketData*>(calloc(socket_map_size_,
sizeof(SocketData)));
@@ -88,48 +92,9 @@ SocketData* EventHandlerImplementation::GetSocketData(intptr_t fd) {
socket_map_size_ = new_socket_map_size;
}
- return socket_map_ + fd;
-}
-
-
-void EventHandlerImplementation::SetPort(intptr_t fd,
- Dart_Port dart_port,
- intptr_t mask) {
- SocketData* sd = GetSocketData(fd);
-
- // Only change the port map entries count if SetPort changes the
- // port map state.
- if (dart_port == 0 && sd->port() != 0) {
- socket_map_entries_--;
- } else if (dart_port != 0 && sd->port() == 0) {
- socket_map_entries_++;
- }
-
- sd->set_port(dart_port);
- sd->set_mask(mask);
-}
-
-
-void EventHandlerImplementation::RegisterFdWakeup(intptr_t id,
- Dart_Port dart_port,
- intptr_t data) {
- WakeupHandler(id, dart_port, data);
-}
-
-
-void EventHandlerImplementation::CloseFd(intptr_t id) {
- SetPort(id, 0, 0);
- close(id);
-}
-
-
-void EventHandlerImplementation::UnregisterFdWakeup(intptr_t id) {
- WakeupHandler(id, 0, 0);
-}
-
-
-void EventHandlerImplementation::UnregisterFd(intptr_t id) {
- SetPort(id, 0, 0);
+ SocketData* sd = socket_map_ + fd;
+ sd->set_fd(fd); // For now just make sure the fd is set.
+ return sd;
}
@@ -151,7 +116,13 @@ void EventHandlerImplementation::WakeupHandler(intptr_t id,
struct pollfd* EventHandlerImplementation::GetPollFds(intptr_t* pollfds_size) {
struct pollfd* pollfds;
- intptr_t numPollfds = 1 + socket_map_entries_;
+ // Calculate the number of file descriptors to poll on.
+ intptr_t numPollfds = 1;
+ for (int i = 0; i < socket_map_size_; i++) {
+ SocketData* sd = &socket_map_[i];
+ if (sd->port() > 0 && sd->GetPollEvents() != 0) numPollfds++;
+ }
+
pollfds = reinterpret_cast<struct pollfd*>(calloc(sizeof(struct pollfd),
numPollfds));
pollfds[0].fd = interrupt_fds_[0];
@@ -161,14 +132,16 @@ struct pollfd* EventHandlerImplementation::GetPollFds(intptr_t* pollfds_size) {
int j = 1;
for (int i = 0; i < socket_map_size_; i++) {
SocketData* sd = &socket_map_[i];
- if (sd->port() != 0) {
+ intptr_t events = sd->GetPollEvents();
+ if (sd->port() > 0 && events != 0) {
// Fd is added to the poll set.
- pollfds[j].fd = i;
- sd->FillPollEvents(&pollfds[j]);
+ pollfds[j].fd = sd->fd();
+ pollfds[j].events = events;
j++;
}
}
- *pollfds_size = numPollfds;
+ ASSERT(numPollfds == j);
+ *pollfds_size = j;
return pollfds;
}
@@ -197,20 +170,53 @@ void EventHandlerImplementation::HandleInterruptFd() {
if (msg.id == kTimerId) {
timeout_ = msg.data;
timeout_port_ = msg.dart_port;
- } else if ((msg.data & (1 << kCloseCommand)) != 0) {
- /*
- * A close event happened in dart, we have to explicitly unregister
- * the fd and close the fd.
- */
- CloseFd(msg.id);
} else {
- SetPort(msg.id, msg.dart_port, msg.data);
+ SocketData* sd = GetSocketData(msg.id);
+ if ((msg.data & (1 << kShutdownReadCommand)) != 0) {
+ ASSERT(msg.data == (1 << kShutdownReadCommand));
+ // Close the socket for reading.
+ sd->ShutdownRead();
+ } else if ((msg.data & (1 << kShutdownWriteCommand)) != 0) {
+ ASSERT(msg.data == (1 << kShutdownWriteCommand));
+ // Close the socket for writing.
+ sd->ShutdownWrite();
+ } else if ((msg.data & (1 << kCloseCommand)) != 0) {
+ ASSERT(msg.data == (1 << kCloseCommand));
+ // Close the socket and free system resources.
+ sd->Close();
+ } else {
+ // Setup events to wait for.
+ sd->SetPortAndMask(msg.dart_port, msg.data);
+ }
}
}
}
+#ifdef DEBUG_POLL
+static void PrintEventMask(struct pollfd* pollfd) {
+ printf("%d ", pollfd->fd);
+ if ((pollfd->revents & POLLIN) != 0) printf("POLLIN ");
+ if ((pollfd->revents & POLLPRI) != 0) printf("POLLPRI ");
+ if ((pollfd->revents & POLLOUT) != 0) printf("POLLOUT ");
+ if ((pollfd->revents & POLLERR) != 0) printf("POLLERR ");
+ if ((pollfd->revents & POLLHUP) != 0) printf("POLLHUP ");
+ if ((pollfd->revents & POLLRDHUP) != 0) printf("POLLRDHUP ");
+ if ((pollfd->revents & POLLNVAL) != 0) printf("POLLNVAL ");
+ int all_events = POLLIN | POLLPRI | POLLOUT |
+ POLLERR | POLLHUP | POLLRDHUP | POLLNVAL;
+ if ((pollfd->revents & ~all_events) != 0) {
+ printf("(and %08x) ", pollfd->revents & ~all_events);
+ }
+ printf("(available %d) ", FDUtils::AvailableBytes(pollfd->fd));
+
+ printf("\n");
+}
+#endif
intptr_t EventHandlerImplementation::GetPollEvents(struct pollfd* pollfd) {
+#ifdef DEBUG_POLL
+ if (pollfd->fd != interrupt_fds_[0]) PrintEventMask(pollfd);
+#endif
intptr_t event_mask = 0;
SocketData* sd = GetSocketData(pollfd->fd);
if (sd->IsListeningSocket()) {
@@ -223,17 +229,41 @@ intptr_t EventHandlerImplementation::GetPollEvents(struct pollfd* pollfd) {
if (event_mask == 0) event_mask |= (1 << kInEvent);
}
} else {
+ if ((pollfd->revents & POLLNVAL) != 0) {
+ return 0;
+ }
+
// Prioritize data events over close and error events.
if ((pollfd->revents & POLLIN) != 0) {
if (FDUtils::AvailableBytes(pollfd->fd) != 0) {
event_mask = (1 << kInEvent);
- } else if ((pollfd->revents & POLLHUP) != 0) {
+ } else if (((pollfd->revents & POLLHUP) != 0)) {
event_mask = (1 << kCloseEvent);
+ sd->MarkClosedRead();
} else if ((pollfd->revents & POLLERR) != 0) {
event_mask = (1 << kErrorEvent);
+ } else {
+ // If POLLIN is set with no available data and no POLLHUP use
+ // recv to peek for whether the other end of the socket
+ // actually closed.
+ char buffer;
+ ssize_t bytesPeeked = recv(sd->fd(), &buffer, 1, MSG_PEEK);
+ if (bytesPeeked == 0) {
+ event_mask = (1 << kCloseEvent);
+ sd->MarkClosedRead();
+ } else if (errno != EAGAIN) {
+ fprintf(stderr, "Error recv: %s\n", strerror(errno));
+ }
}
}
+ // On pipes POLLHUP is reported without POLLIN.
+ if (((pollfd->revents & POLLIN) == 0) &&
+ ((pollfd->revents & POLLHUP) != 0)) {
+ event_mask = (1 << kCloseEvent);
+ sd->MarkClosedRead();
+ }
+
if ((pollfd->revents & POLLOUT) != 0) event_mask |= (1 << kOutEvent);
}
@@ -256,9 +286,10 @@ void EventHandlerImplementation::HandleEvents(struct pollfd* pollfds,
intptr_t event_mask = GetPollEvents(&pollfds[i]);
if (event_mask != 0) {
intptr_t fd = pollfds[i].fd;
- Dart_Port port = GetSocketData(fd)->port();
+ SocketData* sd = GetSocketData(fd);
+ Dart_Port port = sd->port();
ASSERT(port != 0);
- UnregisterFd(fd);
+ sd->Unregister();
Dart_PostIntArray(port, 1, &event_mask);
}
}
@@ -324,5 +355,5 @@ void EventHandlerImplementation::StartEventHandler() {
void EventHandlerImplementation::SendData(intptr_t id,
Dart_Port dart_port,
intptr_t data) {
- RegisterFdWakeup(id, dart_port, data);
+ WakeupHandler(id, dart_port, data);
}
« no previous file with comments | « runtime/bin/eventhandler_macos.h ('k') | runtime/bin/eventhandler_win.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698