@@ -10,6 +10,7 @@ use crate::boxed::ZBox;
10
10
use crate :: ffi:: zend_atomic_bool_store;
11
11
use crate :: ffi:: {
12
12
_sapi_globals_struct, _zend_executor_globals, ext_php_rs_executor_globals,
13
+ _sapi_module_struct, ext_php_rs_sapi_module,
13
14
ext_php_rs_sapi_globals, zend_ini_entry,
14
15
} ;
15
16
use crate :: types:: { ZendHashTable , ZendObject } ;
@@ -20,6 +21,9 @@ pub type ExecutorGlobals = _zend_executor_globals;
20
21
/// Stores global SAPI variables used in the PHP executor.
21
22
pub type SapiGlobals = _sapi_globals_struct ;
22
23
24
+ /// Stores the SAPI module used in the PHP executor.
25
+ pub type SapiModule = _sapi_module_struct ;
26
+
23
27
impl ExecutorGlobals {
24
28
/// Returns a reference to the PHP executor globals.
25
29
///
@@ -167,6 +171,40 @@ impl SapiGlobals {
167
171
}
168
172
}
169
173
174
+ impl SapiModule {
175
+ /// Returns a reference to the PHP SAPI module.
176
+ ///
177
+ /// The executor globals are guarded by a RwLock. There can be multiple
178
+ /// immutable references at one time but only ever one mutable reference.
179
+ /// Attempting to retrieve the globals while already holding the global
180
+ /// guard will lead to a deadlock. Dropping the globals guard will release
181
+ /// the lock.
182
+ pub fn get ( ) -> GlobalReadGuard < Self > {
183
+ // SAFETY: PHP executor globals are statically declared therefore should never
184
+ // return an invalid pointer.
185
+ let globals = unsafe { ext_php_rs_sapi_module ( ) . as_ref ( ) }
186
+ . expect ( "Static executor globals were invalid" ) ;
187
+ let guard = SAPI_MODULE_LOCK . read ( ) ;
188
+ GlobalReadGuard { globals, guard }
189
+ }
190
+
191
+ /// Returns a mutable reference to the PHP executor globals.
192
+ ///
193
+ /// The executor globals are guarded by a RwLock. There can be multiple
194
+ /// immutable references at one time but only ever one mutable reference.
195
+ /// Attempting to retrieve the globals while already holding the global
196
+ /// guard will lead to a deadlock. Dropping the globals guard will release
197
+ /// the lock.
198
+ pub fn get_mut ( ) -> GlobalWriteGuard < Self > {
199
+ // SAFETY: PHP executor globals are statically declared therefore should never
200
+ // return an invalid pointer.
201
+ let globals = unsafe { ext_php_rs_sapi_module ( ) . as_mut ( ) }
202
+ . expect ( "Static executor globals were invalid" ) ;
203
+ let guard = SAPI_MODULE_LOCK . write ( ) ;
204
+ GlobalWriteGuard { globals, guard }
205
+ }
206
+ }
207
+
170
208
/// Executor globals rwlock.
171
209
///
172
210
/// PHP provides no indication if the executor globals are being accessed so
@@ -179,6 +217,12 @@ static GLOBALS_LOCK: RwLock<()> = const_rwlock(());
179
217
/// this is only effective on the Rust side.
180
218
static SAPI_LOCK : RwLock < ( ) > = const_rwlock ( ( ) ) ;
181
219
220
+ /// SAPI globals rwlock.
221
+ ///
222
+ /// PHP provides no indication if the executor globals are being accessed so
223
+ /// this is only effective on the Rust side.
224
+ static SAPI_MODULE_LOCK : RwLock < ( ) > = const_rwlock ( ( ) ) ;
225
+
182
226
/// Wrapper guard that contains a reference to a given type `T`. Dropping a
183
227
/// guard releases the lock on the relevant rwlock.
184
228
pub struct GlobalReadGuard < T : ' static > {
0 commit comments