@@ -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 )
@@ -2261,7 +2287,7 @@ cdef class Loop:
2261
2287
if self ._debug and sock.gettimeout() != 0 :
2262
2288
raise ValueError (" the socket must be non-blocking" )
2263
2289
2264
- fut = self ._new_reader_future (sock)
2290
+ fut = _SyncSocketReaderFuture (sock, self )
2265
2291
handle = new_MethodHandle3(
2266
2292
self ,
2267
2293
" Loop._sock_recv" ,
@@ -2287,7 +2313,7 @@ cdef class Loop:
2287
2313
if self ._debug and sock.gettimeout() != 0 :
2288
2314
raise ValueError (" the socket must be non-blocking" )
2289
2315
2290
- fut = self ._new_reader_future (sock)
2316
+ fut = _SyncSocketReaderFuture (sock, self )
2291
2317
handle = new_MethodHandle3(
2292
2318
self ,
2293
2319
" Loop._sock_recv_into" ,
@@ -2338,7 +2364,7 @@ cdef class Loop:
2338
2364
data = memoryview(data)
2339
2365
data = data[n:]
2340
2366
2341
- fut = self ._new_writer_future (sock)
2367
+ fut = _SyncSocketWriterFuture (sock, self )
2342
2368
handle = new_MethodHandle3(
2343
2369
self ,
2344
2370
" Loop._sock_sendall" ,
@@ -2368,7 +2394,7 @@ cdef class Loop:
2368
2394
if self ._debug and sock.gettimeout() != 0 :
2369
2395
raise ValueError (" the socket must be non-blocking" )
2370
2396
2371
- fut = self ._new_reader_future (sock)
2397
+ fut = _SyncSocketReaderFuture (sock, self )
2372
2398
handle = new_MethodHandle2(
2373
2399
self ,
2374
2400
" Loop._sock_accept" ,
@@ -2952,6 +2978,36 @@ cdef inline void __loop_free_buffer(Loop loop):
2952
2978
loop._recv_buffer_in_use = 0
2953
2979
2954
2980
2981
+ class _SyncSocketReaderFuture (aio_Future ):
2982
+
2983
+ def __init__ (self , sock , loop ):
2984
+ aio_Future.__init__ (self , loop = loop)
2985
+ self .__sock = sock
2986
+ self .__loop = loop
2987
+
2988
+ def cancel (self ):
2989
+ if self .__sock is not None and self .__sock.fileno() != - 1 :
2990
+ self .__loop.remove_reader(self .__sock)
2991
+ self .__sock = None
2992
+
2993
+ aio_Future.cancel(self )
2994
+
2995
+
2996
+ class _SyncSocketWriterFuture (aio_Future ):
2997
+
2998
+ def __init__ (self , sock , loop ):
2999
+ aio_Future.__init__ (self , loop = loop)
3000
+ self .__sock = sock
3001
+ self .__loop = loop
3002
+
3003
+ def cancel (self ):
3004
+ if self .__sock is not None and self .__sock.fileno() != - 1 :
3005
+ self .__loop.remove_writer(self .__sock)
3006
+ self .__sock = None
3007
+
3008
+ aio_Future.cancel(self )
3009
+
3010
+
2955
3011
include " cbhandles.pyx"
2956
3012
include " pseudosock.pyx"
2957
3013
0 commit comments