@@ -194,7 +194,12 @@ cdef class TimerHandle:
194
194
self .context = None
195
195
196
196
if loop._debug:
197
- self ._source_traceback = extract_stack()
197
+ self ._debug_info = (
198
+ format_callback_name(callback),
199
+ extract_stack()
200
+ )
201
+ else :
202
+ self ._debug_info = None
198
203
199
204
self .timer = UVTimer.new(
200
205
loop, < method_t> self ._run, self , delay)
@@ -204,6 +209,11 @@ cdef class TimerHandle:
204
209
# Only add to loop._timers when `self.timer` is successfully created
205
210
loop._timers.add(self )
206
211
212
+ property _source_traceback :
213
+ def __get__ (self ):
214
+ if self ._debug_info is not None :
215
+ return self ._debug_info[1 ]
216
+
207
217
def __dealloc__ (self ):
208
218
if UVLOOP_DEBUG:
209
219
self .loop._debug_cb_timer_handles_count -= 1
@@ -227,7 +237,7 @@ cdef class TimerHandle:
227
237
self .loop._timers.remove(self )
228
238
finally :
229
239
self .timer._close()
230
- self .timer = None # let it die asap
240
+ self .timer = None # let the UVTimer handle GC
231
241
232
242
cdef _run(self ):
233
243
if self ._cancelled == 1 :
@@ -260,8 +270,8 @@ cdef class TimerHandle:
260
270
' handle' : self ,
261
271
}
262
272
263
- if self ._source_traceback is not None :
264
- context[' source_traceback' ] = self ._source_traceback
273
+ if self ._debug_info is not None :
274
+ context[' source_traceback' ] = self ._debug_info[ 1 ]
265
275
266
276
self .loop.call_exception_handler(context)
267
277
else :
@@ -276,6 +286,7 @@ cdef class TimerHandle:
276
286
Py_DECREF(self )
277
287
if PY37:
278
288
Context_Exit(context)
289
+ self ._clear()
279
290
280
291
# Public API
281
292
@@ -285,19 +296,20 @@ cdef class TimerHandle:
285
296
if self ._cancelled:
286
297
info.append(' cancelled' )
287
298
288
- if self .callback is not None :
289
- func = self .callback
290
- if hasattr (func, ' __qualname__' ):
291
- cb_name = getattr (func, ' __qualname__' )
292
- elif hasattr (func, ' __name__' ):
293
- cb_name = getattr (func, ' __name__' )
294
- else :
295
- cb_name = repr (func)
299
+ if self ._debug_info is not None :
300
+ callback_name = self ._debug_info[0 ]
301
+ source_traceback = self ._debug_info[1 ]
302
+ else :
303
+ callback_name = None
304
+ source_traceback = None
296
305
297
- info.append(cb_name)
306
+ if callback_name is not None :
307
+ info.append(callback_name)
308
+ elif self .callback is not None :
309
+ info.append(format_callback_name(self .callback))
298
310
299
- if self ._source_traceback is not None :
300
- frame = self ._source_traceback [- 1 ]
311
+ if source_traceback is not None :
312
+ frame = source_traceback [- 1 ]
301
313
info.append(' created at {}:{}' .format(frame[0 ], frame[1 ]))
302
314
303
315
return ' <' + ' ' .join(info) + ' >'
@@ -309,6 +321,16 @@ cdef class TimerHandle:
309
321
self ._cancel()
310
322
311
323
324
+ cdef format_callback_name(func):
325
+ if hasattr (func, ' __qualname__' ):
326
+ cb_name = getattr (func, ' __qualname__' )
327
+ elif hasattr (func, ' __name__' ):
328
+ cb_name = getattr (func, ' __name__' )
329
+ else :
330
+ cb_name = repr (func)
331
+ return cb_name
332
+
333
+
312
334
cdef new_Handle(Loop loop, object callback, object args, object context):
313
335
cdef Handle handle
314
336
handle = Handle.__new__ (Handle)
0 commit comments