@@ -95,7 +95,18 @@ cdef class Handle:
9595 if self .cb_type == 1 :
9696 cb = self .arg1
9797 if isinstance (getattr (cb, ' __self__' , None ), aio_Task):
98- return repr (cb.__self__)
98+ try :
99+ return repr (cb.__self__)
100+ except (AttributeError , TypeError , ValueError ) as ex:
101+ # Cython generates empty __code__ objects for coroutines
102+ # that can crash asyncio.Task.__repr__ with an
103+ # AttributeError etc. Guard against that.
104+ self .loop.call_exception_handler({
105+ ' message' : ' exception in Task.__repr__' ,
106+ ' task' : cb.__self__,
107+ ' exception' : ex,
108+ ' handle' : self ,
109+ })
99110 return repr (self )
100111
101112 # Public API
@@ -108,10 +119,11 @@ cdef class Handle:
108119
109120 if self .cb_type == 1 :
110121 func = self .arg1
111- if hasattr (func, ' __qualname__' ):
112- cb_name = getattr (func, ' __qualname__' )
113- elif hasattr (func, ' __name__' ):
114- cb_name = getattr (func, ' __name__' )
122+ # Cython can unset func.__qualname__/__name__, hence the checks.
123+ if hasattr (func, ' __qualname__' ) and func.__qualname__:
124+ cb_name = func.__qualname__
125+ elif hasattr (func, ' __name__' ) and func.__name__ :
126+ cb_name = func.__name__
115127 else :
116128 cb_name = repr (func)
117129
0 commit comments