@@ -5,6 +5,19 @@ use std::{
55 path:: { Path , PathBuf } ,
66} ;
77
8+ #[ cfg( target_os = "linux" ) ]
9+ use std:: os:: raw:: c_void;
10+
11+ #[ cfg( target_os = "linux" ) ]
12+ unsafe extern "C" {
13+ fn dlopen ( filename : * const i8 , flag : i32 ) -> * mut c_void ;
14+ }
15+
16+ #[ cfg( target_os = "linux" ) ]
17+ const RTLD_GLOBAL : i32 = 0x100 ;
18+ #[ cfg( target_os = "linux" ) ]
19+ const RTLD_NOW : i32 = 0x2 ;
20+
821use bytes:: BytesMut ;
922use http_handler:: { Handler , Request , RequestExt , Response , extensions:: DocumentRoot } ;
1023use pyo3:: exceptions:: PyRuntimeError ;
@@ -35,6 +48,54 @@ pub use websocket::{
3548 WebSocketConnectionScope , WebSocketReceiveMessage , WebSocketSendException , WebSocketSendMessage ,
3649} ;
3750
51+ /// Load Python library with RTLD_GLOBAL on Linux to make symbols available
52+ #[ cfg( target_os = "linux" ) ]
53+ fn ensure_python_symbols_global ( ) {
54+ unsafe {
55+ // Try to find the system Python library dynamically
56+ use std:: process:: Command ;
57+
58+ // First try to find the Python library using find command
59+ if let Ok ( output) = Command :: new ( "find" )
60+ . args ( & [ "/usr/lib" , "/usr/lib64" , "/usr/local/lib" , "-name" , "libpython3*.so.*" , "-type" , "f" ] )
61+ . output ( )
62+ {
63+ let output_str = String :: from_utf8_lossy ( & output. stdout ) ;
64+ for lib_path in output_str. lines ( ) {
65+ if let Ok ( lib_cstring) = CString :: new ( lib_path) {
66+ let handle = dlopen ( lib_cstring. as_ptr ( ) , RTLD_NOW | RTLD_GLOBAL ) ;
67+ if !handle. is_null ( ) {
68+ // Successfully loaded Python library with RTLD_GLOBAL
69+ return ;
70+ }
71+ }
72+ }
73+ }
74+
75+ // Fallback to common library names if find command fails
76+ let python_libs = [
77+ "libpython3.12.so.1.0\0 " ,
78+ "libpython3.11.so.1.0\0 " ,
79+ "libpython3.10.so.1.0\0 " ,
80+ "libpython3.9.so.1.0\0 " ,
81+ "libpython3.8.so.1.0\0 " ,
82+ ] ;
83+
84+ for lib_name in & python_libs {
85+ let handle = dlopen ( lib_name. as_ptr ( ) as * const i8 , RTLD_NOW | RTLD_GLOBAL ) ;
86+ if !handle. is_null ( ) {
87+ // Successfully loaded Python library with RTLD_GLOBAL
88+ break ;
89+ }
90+ }
91+ }
92+ }
93+
94+ #[ cfg( not( target_os = "linux" ) ) ]
95+ fn ensure_python_symbols_global ( ) {
96+ // On non-Linux platforms, this is typically not needed
97+ }
98+
3899/// Core ASGI handler that loads and manages a Python ASGI application
39100pub struct Asgi {
40101 app_function : PyObject ,
@@ -47,6 +108,9 @@ impl Asgi {
47108 docroot : Option < String > ,
48109 app_target : Option < PythonHandlerTarget > ,
49110 ) -> Result < Self , HandlerError > {
111+ // Ensure Python symbols are globally available before initializing
112+ ensure_python_symbols_global ( ) ;
113+
50114 // Determine document root
51115 let docroot = PathBuf :: from ( if let Some ( docroot) = docroot {
52116 docroot
0 commit comments