@@ -14,17 +14,18 @@ use crate::{classes::ClassEntry, objects::ZObject, sys::*, types::TypeInfo, valu
14
14
use derive_more:: Constructor ;
15
15
use phper_alloc:: ToRefOwned ;
16
16
use std:: {
17
+ cell:: RefCell ,
17
18
convert:: Infallible ,
18
19
error,
19
20
ffi:: FromBytesWithNulError ,
20
21
fmt:: { self , Debug , Display } ,
21
22
io,
22
23
marker:: PhantomData ,
23
- mem:: ManuallyDrop ,
24
+ mem:: { replace , ManuallyDrop } ,
24
25
ops:: { Deref , DerefMut } ,
26
+ ptr:: null_mut,
25
27
result,
26
28
str:: Utf8Error ,
27
- sync:: atomic:: { self , AtomicIsize } ,
28
29
} ;
29
30
30
31
/// Predefined interface `Throwable`.
@@ -466,8 +467,6 @@ impl Throwable for NotImplementThrowableError {
466
467
}
467
468
}
468
469
469
- static EXCEPTION_GUARD_COUNT : AtomicIsize = AtomicIsize :: new ( 0 ) ;
470
-
471
470
/// Guarder for preventing the thrown exception from being overwritten.
472
471
///
473
472
/// Normally, you don't need to use `ExceptionGuard`, unless before you call the
@@ -476,24 +475,26 @@ static EXCEPTION_GUARD_COUNT: AtomicIsize = AtomicIsize::new(0);
476
475
/// Can be used nested.
477
476
pub struct ExceptionGuard ( PhantomData < * mut ( ) > ) ;
478
477
478
+ thread_local ! {
479
+ static EXCEPTION_STACK : RefCell <Vec <* mut zend_object>> = Default :: default ( ) ;
480
+ }
481
+
479
482
impl Default for ExceptionGuard {
480
483
fn default ( ) -> Self {
481
- if EXCEPTION_GUARD_COUNT . fetch_add ( 1 , atomic :: Ordering :: Acquire ) == 0 {
482
- unsafe {
483
- zend_exception_save ( ) ;
484
- }
485
- }
484
+ EXCEPTION_STACK . with ( |stack| unsafe {
485
+ stack
486
+ . borrow_mut ( )
487
+ . push ( replace ( & mut eg ! ( exception ) , null_mut ( ) ) ) ;
488
+ } ) ;
486
489
Self ( PhantomData )
487
490
}
488
491
}
489
492
490
493
impl Drop for ExceptionGuard {
491
494
fn drop ( & mut self ) {
492
- if EXCEPTION_GUARD_COUNT . fetch_sub ( 1 , atomic:: Ordering :: Acquire ) == 1 {
493
- unsafe {
494
- zend_exception_restore ( ) ;
495
- }
496
- }
495
+ EXCEPTION_STACK . with ( |stack| unsafe {
496
+ eg ! ( exception) = stack. borrow_mut ( ) . pop ( ) . expect ( "exception stack is empty" ) ;
497
+ } ) ;
497
498
}
498
499
}
499
500
0 commit comments