@@ -24,6 +24,7 @@ use datafusion::logical_expr::Volatility;
2424use pyo3:: exceptions:: PyValueError ;
2525use pyo3:: prelude:: * ;
2626use pyo3:: types:: PyCapsule ;
27+ use pyo3:: PyErr ;
2728use std:: future:: Future ;
2829use std:: sync:: OnceLock ;
2930use tokio:: runtime:: Runtime ;
@@ -47,14 +48,44 @@ pub(crate) fn get_global_ctx() -> &'static SessionContext {
4748 CTX . get_or_init ( SessionContext :: new)
4849}
4950
50- /// Utility to collect rust futures with GIL released
51- pub fn wait_for_future < F > ( py : Python , f : F ) -> F :: Output
51+ /// Utility to collect rust futures with GIL released and respond to
52+ /// Python interrupts such as ``KeyboardInterrupt``. If a signal is
53+ /// received while the future is running, the future is aborted and the
54+ /// corresponding Python exception is raised.
55+ pub fn wait_for_future < F > ( py : Python , f : F ) -> PyResult < F :: Output >
5256where
53- F : Future + Send ,
54- F :: Output : Send ,
57+ F : Future + Send + ' static ,
58+ F :: Output : Send + ' static ,
5559{
60+ use std:: { thread, time:: Duration } ;
61+ use tokio:: task:: JoinHandle ;
62+
5663 let runtime: & Runtime = & get_tokio_runtime ( ) . 0 ;
57- py. allow_threads ( || runtime. block_on ( f) )
64+
65+ // Spawn the future so it can be aborted if a signal is received
66+ let handle: JoinHandle < F :: Output > = runtime. spawn ( f) ;
67+
68+ let mut interrupt: Option < PyErr > = None ;
69+ py. allow_threads ( || {
70+ while !handle. is_finished ( ) {
71+ thread:: sleep ( Duration :: from_millis ( 10 ) ) ;
72+ Python :: with_gil ( |py| {
73+ if let Err ( err) = py. check_signals ( ) {
74+ handle. abort ( ) ;
75+ interrupt = Some ( err) ;
76+ }
77+ } ) ;
78+ if interrupt. is_some ( ) {
79+ break ;
80+ }
81+ }
82+ } ) ;
83+
84+ if let Some ( err) = interrupt {
85+ return Err ( err) ;
86+ }
87+
88+ Ok ( runtime. block_on ( handle) . expect ( "Tokio task panicked" ) )
5889}
5990
6091pub ( crate ) fn parse_volatility ( value : & str ) -> PyDataFusionResult < Volatility > {
0 commit comments