Skip to content

Commit

Permalink
move socket cleanup into it's own function
Browse files Browse the repository at this point in the history
  • Loading branch information
jakedouglas committed Nov 22, 2009
1 parent 316f05f commit 8a807c9
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 81 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ Makefile
*.pdb
*.dSYM
java/src/.project
*.rbc
131 changes: 50 additions & 81 deletions ext/em.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -545,47 +545,7 @@ bool EventMachine_t::_RunEpollOnce()
}

_DispatchHeartbeats();

{ // cleanup dying sockets
// vector::pop_back works in constant time.
// TODO, rip this out and only delete the descriptors we know have died,
// rather than traversing the whole list.
// Modified 05Jan08 per suggestions by Chris Heath. It's possible that
// an EventableDescriptor will have a descriptor value of -1. That will
// happen if EventableDescriptor::Close was called on it. In that case,
// don't call epoll_ctl to remove the socket's filters from the epoll set.
// According to the epoll docs, this happens automatically when the
// descriptor is closed anyway. This is different from the case where
// the socket has already been closed but the descriptor in the ED object
// hasn't yet been set to INVALID_SOCKET.
int i, j;
int nSockets = Descriptors.size();
for (i=0, j=0; i < nSockets; i++) {
EventableDescriptor *ed = Descriptors[i];
assert (ed);
if (ed->ShouldDelete()) {
if (ed->GetSocket() != INVALID_SOCKET) {
assert (bEpoll); // wouldn't be in this method otherwise.
assert (epfd != -1);
int e = epoll_ctl (epfd, EPOLL_CTL_DEL, ed->GetSocket(), ed->GetEpollEvent());
// ENOENT or EBADF are not errors because the socket may be already closed when we get here.
if (e && (errno != ENOENT) && (errno != EBADF) && (errno != EPERM)) {
char buf [200];
snprintf (buf, sizeof(buf)-1, "unable to delete epoll event: %s", strerror(errno));
throw std::runtime_error (buf);
}
}

ModifiedDescriptors.erase (ed);
delete ed;
}
else
Descriptors [j++] = ed;
}
while ((size_t)j < Descriptors.size())
Descriptors.pop_back();

}
_CleanupSockets();

#ifdef BUILD_FOR_RUBY
if (!rb_thread_alone()) {
Expand Down Expand Up @@ -654,29 +614,7 @@ bool EventMachine_t::_RunKqueueOnce()
}

_DispatchHeartbeats();

{ // cleanup dying sockets
// vector::pop_back works in constant time.
// TODO, rip this out and only delete the descriptors we know have died,
// rather than traversing the whole list.
// In kqueue, closing a descriptor automatically removes its event filters.

int i, j;
int nSockets = Descriptors.size();
for (i=0, j=0; i < nSockets; i++) {
EventableDescriptor *ed = Descriptors[i];
assert (ed);
if (ed->ShouldDelete()) {
ModifiedDescriptors.erase (ed);
delete ed;
}
else
Descriptors [j++] = ed;
}
while ((size_t)j < Descriptors.size())
Descriptors.pop_back();

}
_CleanupSockets();

// TODO, replace this with rb_thread_blocking_region for 1.9 builds.
#ifdef BUILD_FOR_RUBY
Expand All @@ -692,6 +630,53 @@ bool EventMachine_t::_RunKqueueOnce()
}


/*******************************
EventMachine_t::_CleanupSockets
*******************************/

void EventMachine_t::_CleanupSockets()
{
// TODO, rip this out and only delete the descriptors we know have died,
// rather than traversing the whole list.
// Modified 05Jan08 per suggestions by Chris Heath. It's possible that
// an EventableDescriptor will have a descriptor value of -1. That will
// happen if EventableDescriptor::Close was called on it. In that case,
// don't call epoll_ctl to remove the socket's filters from the epoll set.
// According to the epoll docs, this happens automatically when the
// descriptor is closed anyway. This is different from the case where
// the socket has already been closed but the descriptor in the ED object
// hasn't yet been set to INVALID_SOCKET.
// In kqueue, closing a descriptor automatically removes its event filters.
int i, j;
int nSockets = Descriptors.size();
for (i=0, j=0; i < nSockets; i++) {
EventableDescriptor *ed = Descriptors[i];
assert (ed);
if (ed->ShouldDelete()) {
#ifdef HAVE_EPOLL
if (bEpoll) {
assert (epfd != -1);
if (ed->GetSocket() != INVALID_SOCKET) {
int e = epoll_ctl (epfd, EPOLL_CTL_DEL, ed->GetSocket(), ed->GetEpollEvent());
// ENOENT or EBADF are not errors because the socket may be already closed when we get here.
if (e && (errno != ENOENT) && (errno != EBADF) && (errno != EPERM)) {
char buf [200];
snprintf (buf, sizeof(buf)-1, "unable to delete epoll event: %s", strerror(errno));
throw std::runtime_error (buf);
}
}
ModifiedDescriptors.erase(ed);
}
#endif
delete ed;
}
else
Descriptors [j++] = ed;
}
while ((size_t)j < Descriptors.size())
Descriptors.pop_back();
}

/*********************************
EventMachine_t::_ModifyEpollEvent
*********************************/
Expand Down Expand Up @@ -890,23 +875,7 @@ bool EventMachine_t::_RunSelectOnce()
}

_DispatchHeartbeats();

{ // cleanup dying sockets
// vector::pop_back works in constant time.
int i, j;
int nSockets = Descriptors.size();
for (i=0, j=0; i < nSockets; i++) {
EventableDescriptor *ed = Descriptors[i];
assert (ed);
if (ed->ShouldDelete())
delete ed;
else
Descriptors [j++] = ed;
}
while ((size_t)j < Descriptors.size())
Descriptors.pop_back();

}
_CleanupSockets();

return true;
}
Expand Down
1 change: 1 addition & 0 deletions ext/em.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ class EventMachine_t
void _AddNewDescriptors();
void _ModifyDescriptors();
void _InitializeLoopBreaker();
void _CleanupSockets();

bool _RunSelectOnce();
bool _RunEpollOnce();
Expand Down

0 comments on commit 8a807c9

Please sign in to comment.