Ticket #6287: fix-epoll-not-calling-connectionRefused

File fix-epoll-not-calling-connectionRefused, 3.6 KB (added by Martin Gergov, 6 years ago)

_doReadOrWrite modification was needed so that TCP preserved it's behaviour, although still looks like a hack.

Line 
1Index: twisted/topfiles/6287.bugfix
2===================================================================
3--- twisted/topfiles/6287.bugfix        (revision 0)
4+++ twisted/topfiles/6287.bugfix        (working copy)
5@@ -0,0 +1 @@
6+Epoll reactor calls connectionRefused on UDP after ICMP Destination unreachable
7\ No newline at end of file
8Index: twisted/internet/posixbase.py
9===================================================================
10--- twisted/internet/posixbase.py       (revision 38625)
11+++ twisted/internet/posixbase.py       (working copy)
12@@ -597,9 +597,13 @@
13                     why = _NO_FILEDESC
14                 else:
15                     if event & self._POLL_IN:
16-                        # Handle a read event.
17-                        why = selectable.doRead()
18-                        inRead = True
19+                        if hasattr(self, '_reads') and fd not in self._reads:
20+                            why = CONNECTION_LOST
21+                        else:
22+                            #Handle a read even.
23+                            why = selectable.doRead()
24+                            inRead = True
25+                           
26                     if not why and event & self._POLL_OUT:
27                         # Handle a write event, as long as doRead didn't
28                         # disconnect us.
29Index: twisted/internet/epollreactor.py
30===================================================================
31--- twisted/internet/epollreactor.py    (revision 38625)
32+++ twisted/internet/epollreactor.py    (working copy)
33@@ -191,8 +191,8 @@
34     """
35 
36     # Attributes for _PollLikeMixin
37-    _POLL_DISCONNECTED = (EPOLLHUP | EPOLLERR)
38-    _POLL_IN = EPOLLIN
39+    _POLL_DISCONNECTED = EPOLLHUP
40+    _POLL_IN = (EPOLLIN  | EPOLLERR)
41     _POLL_OUT = EPOLLOUT
42 
43     def __init__(self):
44Index: twisted/internet/test/test_udp.py
45===================================================================
46--- twisted/internet/test/test_udp.py   (revision 38625)
47+++ twisted/internet/test/test_udp.py   (working copy)
48@@ -25,8 +25,11 @@
49 
50 from twisted.internet.test.connectionmixins import (LogObserverMixin,
51                                                     findFreePort)
52+from twisted.internet.glib2reactor import Glib2Reactor
53+from twisted.internet.gtk2reactor import Gtk2Reactor
54+from twisted.internet.pollreactor import PollReactor
55+from twisted.trial.unittest import SkipTest
56 
57-
58 class UDPPortMixin(object):
59     def getListeningPort(self, reactor, protocol):
60         """
61@@ -215,4 +218,31 @@
62         port = reactor.listenUDP(0, DatagramProtocol())
63         self.assertIn(repr(port.getHost().port), str(port))
64 
65+    def test_connnectionRefusedAfterWrite(self):
66+        class RefuseProtocol(DatagramProtocol):
67+            refused = None
68+            def startProtocol(self):
69+                self.transport.connect('127.0.0.1', 8000)
70+                self.sendDatagram()
71+            def sendDatagram(self):
72+                self.transport.write('a')
73+            def connectionRefused(self):
74+                reactor.callLater(0, self.refused.callback, None)
75+            def datagramReceived(self, datagram, host):
76+                pass
77+
78+        def cbClean(ignore):
79+            reactor.stop()
80+        reactor = self.buildReactor()
81+        if type(reactor) in [Glib2Reactor, Gtk2Reactor, PollReactor]:
82+            raise SkipTest("Reactor does not support refusing after writing")
83+        protocol = RefuseProtocol()
84+        protocol.refused = Deferred()
85+        protocol.refused.addCallback(cbClean)
86+        port = reactor.listenUDP(0, protocol)
87+        self.runReactor(reactor)
88+        return port.stopListening()
89+
90+
91+
92 globals().update(UDPServerTestsBuilder.makeTestCaseClasses())