aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/event/Loop.cxx9
-rw-r--r--src/event/Loop.hxx7
-rw-r--r--src/event/SocketMonitor.cxx13
-rw-r--r--src/event/SocketMonitor.hxx5
4 files changed, 32 insertions, 2 deletions
diff --git a/src/event/Loop.cxx b/src/event/Loop.cxx
index 665dfa500..5aa24aea2 100644
--- a/src/event/Loop.cxx
+++ b/src/event/Loop.cxx
@@ -58,13 +58,18 @@ EventLoop::Break()
AddCall([this]() { Break(); });
}
-bool
-EventLoop::RemoveFD(int _fd, SocketMonitor &m)
+void
+EventLoop::Abandon(SocketMonitor &m)
{
for (unsigned i = 0, n = n_events; i < n; ++i)
if (events[i].data.ptr == &m)
events[i].events = 0;
+}
+bool
+EventLoop::RemoveFD(int _fd, SocketMonitor &m)
+{
+ Abandon(m);
return epoll.Remove(_fd);
}
diff --git a/src/event/Loop.hxx b/src/event/Loop.hxx
index 859ce2733..62e733747 100644
--- a/src/event/Loop.hxx
+++ b/src/event/Loop.hxx
@@ -121,6 +121,13 @@ public:
return epoll.Modify(_fd, flags, &m);
}
+ /**
+ * Remove the given #SocketMonitor after the file descriptor
+ * has been closed. This is like RemoveFD(), but does not
+ * attempt to use #EPOLL_CTL_DEL.
+ */
+ void Abandon(SocketMonitor &m);
+
bool RemoveFD(int fd, SocketMonitor &m);
void AddIdle(IdleMonitor &i);
diff --git a/src/event/SocketMonitor.cxx b/src/event/SocketMonitor.cxx
index 7c118cfd6..2b97059f7 100644
--- a/src/event/SocketMonitor.cxx
+++ b/src/event/SocketMonitor.cxx
@@ -152,6 +152,19 @@ SocketMonitor::Steal()
}
void
+SocketMonitor::Abandon()
+{
+ assert(IsDefined());
+
+#ifdef USE_EPOLL
+ fd = -1;
+ loop.Abandon(*this);
+#else
+ Steal();
+#endif
+}
+
+void
SocketMonitor::Close()
{
close_socket(Steal());
diff --git a/src/event/SocketMonitor.hxx b/src/event/SocketMonitor.hxx
index d6efeac17..5369ddb8a 100644
--- a/src/event/SocketMonitor.hxx
+++ b/src/event/SocketMonitor.hxx
@@ -118,6 +118,11 @@ public:
*/
int Steal();
+ /**
+ * Somebody has closed the socket. Unregister this object.
+ */
+ void Abandon();
+
void Close();
unsigned GetScheduledFlags() const {