@@ -742,6 +742,20 @@ cdef class Loop:
742
742
743
743
return result
744
744
745
+ cdef _has_reader(self , fileobj):
746
+ cdef:
747
+ UVPoll poll
748
+
749
+ self ._check_closed()
750
+ fd = self ._fileobj_to_fd(fileobj)
751
+
752
+ try :
753
+ poll = < UVPoll> (self ._polls[fd])
754
+ except KeyError :
755
+ return False
756
+
757
+ return poll.is_reading()
758
+
745
759
cdef _add_writer(self , fileobj, Handle handle):
746
760
cdef:
747
761
UVPoll poll
@@ -791,6 +805,20 @@ cdef class Loop:
791
805
792
806
return result
793
807
808
+ cdef _has_writer(self , fileobj):
809
+ cdef:
810
+ UVPoll poll
811
+
812
+ self ._check_closed()
813
+ fd = self ._fileobj_to_fd(fileobj)
814
+
815
+ try :
816
+ poll = < UVPoll> (self ._polls[fd])
817
+ except KeyError :
818
+ return False
819
+
820
+ return poll.is_writing()
821
+
794
822
cdef _getaddrinfo(self , object host, object port,
795
823
int family, int type ,
796
824
int proto, int flags,
@@ -845,35 +873,17 @@ cdef class Loop:
845
873
nr.query(addr, flags)
846
874
return fut
847
875
848
- cdef _new_reader_future(self , sock):
849
- def _on_cancel (fut ):
850
- # Check if the future was cancelled and if the socket
851
- # is still open, i.e.
852
- #
853
- # loop.remove_reader(sock)
854
- # sock.close()
855
- # fut.cancel()
856
- #
857
- # wasn't called by the user.
858
- if fut.cancelled() and sock.fileno() != - 1 :
859
- self ._remove_reader(sock)
860
-
861
- fut = self ._new_future()
862
- fut.add_done_callback(_on_cancel)
863
- return fut
864
-
865
- cdef _new_writer_future(self , sock):
866
- def _on_cancel (fut ):
867
- if fut.cancelled() and sock.fileno() != - 1 :
868
- self ._remove_writer(sock)
869
-
870
- fut = self ._new_future()
871
- fut.add_done_callback(_on_cancel)
872
- return fut
873
-
874
876
cdef _sock_recv(self , fut, sock, n):
875
- cdef:
876
- Handle handle
877
+ if UVLOOP_DEBUG:
878
+ if fut.cancelled():
879
+ # Shouldn't happen with _SyncSocketReaderFuture.
880
+ raise RuntimeError (
881
+ f' _sock_recv is called on a cancelled Future' )
882
+
883
+ if not self ._has_reader(sock):
884
+ raise RuntimeError (
885
+ f' socket {sock!r} does not have a reader '
886
+ f' in the _sock_recv callback' )
877
887
878
888
try :
879
889
data = sock.recv(n)
@@ -889,8 +899,16 @@ cdef class Loop:
889
899
self ._remove_reader(sock)
890
900
891
901
cdef _sock_recv_into(self , fut, sock, buf):
892
- cdef:
893
- Handle handle
902
+ if UVLOOP_DEBUG:
903
+ if fut.cancelled():
904
+ # Shouldn't happen with _SyncSocketReaderFuture.
905
+ raise RuntimeError (
906
+ f' _sock_recv_into is called on a cancelled Future' )
907
+
908
+ if not self ._has_reader(sock):
909
+ raise RuntimeError (
910
+ f' socket {sock!r} does not have a reader '
911
+ f' in the _sock_recv_into callback' )
894
912
895
913
try :
896
914
data = sock.recv_into(buf)
@@ -910,6 +928,17 @@ cdef class Loop:
910
928
Handle handle
911
929
int n
912
930
931
+ if UVLOOP_DEBUG:
932
+ if fut.cancelled():
933
+ # Shouldn't happen with _SyncSocketReaderFuture.
934
+ raise RuntimeError (
935
+ f' _sock_sendall is called on a cancelled Future' )
936
+
937
+ if not self ._has_writer(sock):
938
+ raise RuntimeError (
939
+ f' socket {sock!r} does not have a writer '
940
+ f' in the _sock_sendall callback' )
941
+
913
942
try :
914
943
n = sock.send(data)
915
944
except (BlockingIOError, InterruptedError):
@@ -940,9 +969,6 @@ cdef class Loop:
940
969
self ._add_writer(sock, handle)
941
970
942
971
cdef _sock_accept(self , fut, sock):
943
- cdef:
944
- Handle handle
945
-
946
972
try :
947
973
conn, address = sock.accept()
948
974
conn.setblocking(False )
@@ -2217,7 +2243,7 @@ cdef class Loop:
2217
2243
if self ._debug and sock.gettimeout() != 0 :
2218
2244
raise ValueError (" the socket must be non-blocking" )
2219
2245
2220
- fut = self ._new_reader_future (sock)
2246
+ fut = _SyncSocketReaderFuture (sock, self )
2221
2247
handle = new_MethodHandle3(
2222
2248
self ,
2223
2249
" Loop._sock_recv" ,
@@ -2243,7 +2269,7 @@ cdef class Loop:
2243
2269
if self ._debug and sock.gettimeout() != 0 :
2244
2270
raise ValueError (" the socket must be non-blocking" )
2245
2271
2246
- fut = self ._new_reader_future (sock)
2272
+ fut = _SyncSocketReaderFuture (sock, self )
2247
2273
handle = new_MethodHandle3(
2248
2274
self ,
2249
2275
" Loop._sock_recv_into" ,
@@ -2294,7 +2320,7 @@ cdef class Loop:
2294
2320
data = memoryview(data)
2295
2321
data = data[n:]
2296
2322
2297
- fut = self ._new_writer_future (sock)
2323
+ fut = _SyncSocketWriterFuture (sock, self )
2298
2324
handle = new_MethodHandle3(
2299
2325
self ,
2300
2326
" Loop._sock_sendall" ,
@@ -2324,7 +2350,7 @@ cdef class Loop:
2324
2350
if self ._debug and sock.gettimeout() != 0 :
2325
2351
raise ValueError (" the socket must be non-blocking" )
2326
2352
2327
- fut = self ._new_reader_future (sock)
2353
+ fut = _SyncSocketReaderFuture (sock, self )
2328
2354
handle = new_MethodHandle2(
2329
2355
self ,
2330
2356
" Loop._sock_accept" ,
@@ -2908,6 +2934,36 @@ cdef inline void __loop_free_buffer(Loop loop):
2908
2934
loop._recv_buffer_in_use = 0
2909
2935
2910
2936
2937
+ class _SyncSocketReaderFuture (aio_Future ):
2938
+
2939
+ def __init__ (self , sock , loop ):
2940
+ aio_Future.__init__ (self , loop = loop)
2941
+ self .__sock = sock
2942
+ self .__loop = loop
2943
+
2944
+ def cancel (self ):
2945
+ if self .__sock is not None and self .__sock.fileno() != - 1 :
2946
+ self .__loop.remove_reader(self .__sock)
2947
+ self .__sock = None
2948
+
2949
+ aio_Future.cancel(self )
2950
+
2951
+
2952
+ class _SyncSocketWriterFuture (aio_Future ):
2953
+
2954
+ def __init__ (self , sock , loop ):
2955
+ aio_Future.__init__ (self , loop = loop)
2956
+ self .__sock = sock
2957
+ self .__loop = loop
2958
+
2959
+ def cancel (self ):
2960
+ if self .__sock is not None and self .__sock.fileno() != - 1 :
2961
+ self .__loop.remove_writer(self .__sock)
2962
+ self .__sock = None
2963
+
2964
+ aio_Future.cancel(self )
2965
+
2966
+
2911
2967
include " cbhandles.pyx"
2912
2968
include " pseudosock.pyx"
2913
2969
0 commit comments