@@ -1921,34 +1921,56 @@ def on_task_done(t: asyncio.Task):
19211921 asyncio .gather (* created_tasks , return_exceptions = True )
19221922 )
19231923 finally :
1924- if settings .DEEPEVAL_DEBUG_ASYNC :
1924+
1925+ # if it is already closed, we are done
1926+ if loop .is_closed ():
1927+ return
1928+
1929+ try :
19251930 # Find tasks that were created during this run but we didn’t track
19261931 current_tasks = loop .run_until_complete (_snapshot_tasks ())
1927- leftovers = [
1928- t
1929- for t in current_tasks
1930- if t not in baseline_tasks
1931- and t not in created_tasks
1932- and not t .done ()
1933- ]
1934- if leftovers :
1935- logger .warning (
1936- "[deepeval] %d stray task(s) not tracked; cancelling…" ,
1937- len (leftovers ),
1932+ except RuntimeError :
1933+ # this might happen if the loop is already closing
1934+ # nothing we can do
1935+ return
1936+
1937+ leftovers = [
1938+ t
1939+ for t in current_tasks
1940+ if t not in baseline_tasks
1941+ and t not in created_tasks
1942+ and not t .done ()
1943+ ]
1944+
1945+ if not leftovers :
1946+ return
1947+
1948+ if settings .DEEPEVAL_DEBUG_ASYNC :
1949+ logger .warning (
1950+ "[deepeval] %d stray task(s) not tracked; cancelling…" ,
1951+ len (leftovers ),
1952+ )
1953+ for t in leftovers :
1954+ meta = task_meta .get (t , {})
1955+ # Use get_name() if available, else repr()
1956+ name = (
1957+ t .get_name () if hasattr (t , "get_name" ) else repr (t )
19381958 )
1939- for t in leftovers :
1940- meta = task_meta .get (t , {})
1941- # Use get_name() if available, else repr()
1942- name = (
1943- t .get_name ()
1944- if hasattr (t , "get_name" )
1945- else repr (t )
1946- )
1947- logger .warning (" - STRAY %s meta=%s" , name , meta )
1948- t .cancel ()
1949- # Drain strays so they don’t leak into the next iteration
1950- loop .run_until_complete (
1951- asyncio .gather (* leftovers , return_exceptions = True )
1959+ logger .warning (" - STRAY %s meta=%s" , name , meta )
1960+
1961+ for t in leftovers :
1962+ t .cancel ()
1963+
1964+ # Drain strays so they don’t leak into the next iteration
1965+ try :
1966+ loop .run_until_complete (
1967+ asyncio .gather (* leftovers , return_exceptions = True )
1968+ )
1969+ except RuntimeError :
1970+ # If the loop is closing here, just continue
1971+ if settings .DEEPEVAL_DEBUG_ASYNC :
1972+ logger .warning (
1973+ "[deepeval] failed to drain stray tasks because loop is closing"
19521974 )
19531975
19541976 # Evaluate traces
0 commit comments