@@ -4,7 +4,6 @@ export runtests, addworkers, addworker
44
55using Distributed
66using Dates
7- import REPL
87using Printf: @sprintf
98using Base. Filesystem: path_separator
109import Test
@@ -423,9 +422,9 @@ function runtests(ARGS; testfilter = Returns(true), RecordType = TestRecord,
423422
424423 # list tests, if requested
425424 if do_list
426- println (" Available tests:" )
425+ println (stdout , " Available tests:" )
427426 for test in sort (tests)
428- println (" - $test " )
427+ println (stdout , " - $test " )
429428 end
430429 exit (0 )
431430 end
@@ -451,15 +450,14 @@ function runtests(ARGS; testfilter = Returns(true), RecordType = TestRecord,
451450
452451 t0 = time ()
453452 results = []
454- tasks = Task[]
455453 running_tests = Dict {String, Tuple{Int, Float64}} () # test => (worker, start_time)
456454 test_lock = ReentrantLock () # to protect crucial access to tests and running_tests
457455
458456 done = false
459457 function stop_work ()
460458 if ! done
461459 done = true
462- for task in tasks
460+ for task in worker_tasks
463461 task == current_task () && continue
464462 Base. istaskdone (task) && continue
465463 try ; schedule (task, InterruptException (); error= true ); catch ; end
@@ -468,33 +466,6 @@ function runtests(ARGS; testfilter = Returns(true), RecordType = TestRecord,
468466 end
469467
470468
471- #
472- # input
473- #
474-
475- # Keyboard monitor (for more reliable CTRL-C handling)
476- if isa (stdin , Base. TTY)
477- # NOTE: this should be the first task; we really want it to complete
478- pushfirst! (tasks, @async begin
479- term = REPL. Terminals. TTYTerminal (" xterm" , stdin , stdout , stderr )
480- REPL. Terminals. raw! (term, true )
481- try
482- while ! done
483- c = read (term, Char)
484- if c == ' \x 3'
485- println (stderr , " \n Caught interrupt, stopping..." )
486- stop_work ()
487- break
488- end
489- end
490- finally
491- REPL. Terminals. raw! (term, false )
492- end
493- end )
494- end
495- # TODO : we have to be _fast_ here, as Pkg.jl only gives us 4 seconds to clean up
496-
497-
498469 #
499470 # output
500471 #
@@ -626,6 +597,13 @@ function runtests(ARGS; testfilter = Returns(true), RecordType = TestRecord,
626597 sleep (0.1 )
627598 end
628599 catch ex
600+ if isa (ex, InterruptException)
601+ # the printer should keep on running,
602+ # but we need to signal other tasks to stop
603+ stop_work ()
604+ else
605+ rethrow ()
606+ end
629607 isa (ex, InterruptException) || rethrow ()
630608 finally
631609 if isempty (tests) && isempty (running_tests)
@@ -641,8 +619,9 @@ function runtests(ARGS; testfilter = Returns(true), RecordType = TestRecord,
641619 # execution
642620 #
643621
622+ worker_tasks = Task[]
644623 for p in workers ()
645- push! (tasks , @async begin
624+ push! (worker_tasks , @async begin
646625 while length (tests) > 0 && ! done
647626 # if a worker failed, spawn a new one
648627 if p === nothing
@@ -665,7 +644,13 @@ function runtests(ARGS; testfilter = Returns(true), RecordType = TestRecord,
665644 result = try
666645 remotecall_fetch (runtest, wrkr, RecordType, test_runners[test], test, init_code)
667646 catch ex
668- isa (ex, InterruptException) && return
647+ if isa (ex, InterruptException)
648+ # the worker got interrupted, signal other tasks to stop
649+ stop_work ()
650+ return
651+ end
652+
653+ # return any other exception as the result
669654 # XXX : also put this in a test record?
670655 ex
671656 end
@@ -700,10 +685,6 @@ function runtests(ARGS; testfilter = Returns(true), RecordType = TestRecord,
700685
701686 delete! (running_tests, test)
702687 end
703-
704- if p != = nothing
705- recycle_worker (p)
706- end
707688 end )
708689 end
709690
@@ -712,10 +693,10 @@ function runtests(ARGS; testfilter = Returns(true), RecordType = TestRecord,
712693 # finalization
713694 #
714695
715- # monitor tasks for failure so that each one doesn't need a try/catch + stop_work()
696+ # monitor worker tasks for failure so that each one doesn't need a try/catch + stop_work()
716697 try
717698 while true
718- if any (istaskfailed, tasks )
699+ if any (istaskfailed, worker_tasks )
719700 println (io_ctx. stderr , " \n Caught an error, stopping..." )
720701 break
721702 elseif done || Base. @lock (test_lock, isempty (tests) && isempty (running_tests))
@@ -729,10 +710,13 @@ function runtests(ARGS; testfilter = Returns(true), RecordType = TestRecord,
729710 finally
730711 stop_work ()
731712 end
732- # # `wait()` to actually catch any exceptions
713+
714+ # wait for the printer to finish so that all results have been printed
733715 close (printer_channel)
734716 wait (printer_task)
735- for task in tasks
717+
718+ # wait for worker tasks to catch unhandled exceptions
719+ for task in worker_tasks
736720 try
737721 wait (task)
738722 catch err
@@ -744,6 +728,7 @@ function runtests(ARGS; testfilter = Returns(true), RecordType = TestRecord,
744728 isa (err, InterruptException) || rethrow ()
745729 end
746730 end
731+ @async rmprocs (; waitfor= 0 )
747732
748733 # print the output generated by each testset
749734 for (testname, result, start, stop) in results
@@ -881,7 +866,8 @@ function runtests(ARGS; testfilter = Returns(true), RecordType = TestRecord,
881866 end
882867 throw (Test. FallbackTestSetException (" Test run finished with errors" ))
883868 end
884- return nothing
869+
870+ return
885871end # runtests
886872
887873end # module ParallelTestRunner
0 commit comments