summaryrefslogtreecommitdiff
blob: 214c78570c0473a855158c10275d2a5d37a6f280 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# Fixes a crash in epoll due to libcurl/c-ares bug:
# PollEPoll::modify(...) epoll_ctl call failed
Index: libtorrent/src/torrent/poll_epoll.cc
===================================================================
--- libtorrent/src/torrent/poll_epoll.cc	(revision 1067)
+++ libtorrent/src/torrent/poll_epoll.cc	(working copy)
@@ -75,12 +75,21 @@
 
   set_event_mask(event, mask);
 
-  // If error is EEXIST, try again with EPOLL_CTL_MOD.
-  // libcurl with c-ares may unwittingly re-open an FD closed by
-  // c-ares before notified (and thus notifying us) of its closure.
   if (epoll_ctl(m_fd, op, event->file_descriptor(), &e)) {
-    if (op != EPOLL_CTL_ADD || errno != EEXIST ||
-        epoll_ctl(m_fd, EPOLL_CTL_MOD, event->file_descriptor(), &e))
+    // Socket was probably already closed. Ignore this.
+    if (op == EPOLL_CTL_DEL && errno == ENOENT)
+      return;
+
+    // Handle some libcurl/c-ares bugs by retrying once.
+    if (op == EPOLL_CTL_ADD && errno == EEXIST) {
+      op = EPOLL_CTL_MOD;
+      errno = 0;
+    } else if (op == EPOLL_CTL_MOD && errno == ENOENT) {
+      op = EPOLL_CTL_ADD;
+      errno = 0;
+    }
+
+    if (errno || epoll_ctl(m_fd, op, event->file_descriptor(), &e))
       throw internal_error("PollEPoll::modify(...) epoll_ctl call failed");
   }
 }