Skip to content

Commit 411ee6c

Browse files
committed
feat(sapi): split try_catch / try_catch_first, global feature for test
1 parent 4f74bfc commit 411ee6c

File tree

5 files changed

+71
-83
lines changed

5 files changed

+71
-83
lines changed

src/embed/mod.rs

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ impl Embed {
9090
zend_stream_init_filename(&mut file_handle, path.as_ptr());
9191
}
9292

93-
let exec_result = try_catch(|| unsafe { php_execute_script(&mut file_handle) }, false);
93+
let exec_result = try_catch(|| unsafe { php_execute_script(&mut file_handle) });
9494

9595
match exec_result {
9696
Err(_) => Err(EmbedError::CatchError),
@@ -184,16 +184,13 @@ impl Embed {
184184

185185
let mut result = Zval::new();
186186

187-
let exec_result = try_catch(
188-
|| unsafe {
189-
zend_eval_string(
190-
cstr.as_ptr() as *const c_char,
191-
&mut result,
192-
b"run\0".as_ptr() as *const _,
193-
)
194-
},
195-
false,
196-
);
187+
let exec_result = try_catch(|| unsafe {
188+
zend_eval_string(
189+
cstr.as_ptr() as *const c_char,
190+
&mut result,
191+
b"run\0".as_ptr() as *const _,
192+
)
193+
});
197194

198195
match exec_result {
199196
Err(_) => Err(EmbedError::CatchError),

src/zend/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ pub use ini_entry_def::IniEntryDef;
2525
pub use module::ModuleEntry;
2626
#[cfg(feature = "embed")]
2727
pub(crate) use try_catch::panic_wrapper;
28-
pub use try_catch::{bailout, try_catch};
28+
pub use try_catch::{bailout, try_catch, try_catch_first};
2929

3030
// Used as the format string for `php_printf`.
3131
const FORMAT_STR: &[u8] = b"%s\0";

src/zend/try_catch.rs

Lines changed: 48 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,28 @@ pub(crate) unsafe extern "C" fn panic_wrapper<R, F: FnMut() -> R + RefUnwindSafe
2828
///
2929
/// * `Ok(R)` - The result of the function
3030
/// * `Err(CatchError)` - A bailout occurred during the execution
31-
pub fn try_catch<R, F: FnMut() -> R + RefUnwindSafe>(
32-
func: F,
33-
first: bool,
34-
) -> Result<R, CatchError> {
31+
pub fn try_catch<R, F: FnMut() -> R + RefUnwindSafe>(func: F) -> Result<R, CatchError> {
32+
do_try_catch(func, false)
33+
}
34+
35+
/// PHP propose a try catch mechanism in C using setjmp and longjmp (bailout)
36+
/// It store the arg of setjmp into the bailout field of the global executor
37+
/// If a bailout is triggered, the executor will jump to the setjmp and restore the previous setjmp
38+
///
39+
/// try_catch_first allow to use this mechanism
40+
///
41+
/// This functions differs from ['try_catch'] as it also initialize the bailout mechanism
42+
/// for the first time
43+
///
44+
/// # Returns
45+
///
46+
/// * `Ok(R)` - The result of the function
47+
/// * `Err(CatchError)` - A bailout occurred during the execution
48+
pub fn try_catch_first<R, F: FnMut() -> R + RefUnwindSafe>(func: F) -> Result<R, CatchError> {
49+
do_try_catch(func, true)
50+
}
51+
52+
fn do_try_catch<R, F: FnMut() -> R + RefUnwindSafe>(func: F, first: bool) -> Result<R, CatchError> {
3553
let mut panic_ptr = null_mut();
3654
let has_bailout = unsafe {
3755
if first {
@@ -91,19 +109,16 @@ mod tests {
91109
#[test]
92110
fn test_catch() {
93111
Embed::run(|| {
94-
let catch = try_catch(
95-
|| {
96-
unsafe {
97-
bailout();
98-
}
99-
100-
#[allow(unreachable_code)]
101-
{
102-
assert!(false);
103-
}
104-
},
105-
false,
106-
);
112+
let catch = try_catch(|| {
113+
unsafe {
114+
bailout();
115+
}
116+
117+
#[allow(unreachable_code)]
118+
{
119+
assert!(false);
120+
}
121+
});
107122

108123
assert!(catch.is_err());
109124
});
@@ -112,12 +127,9 @@ mod tests {
112127
#[test]
113128
fn test_no_catch() {
114129
Embed::run(|| {
115-
let catch = try_catch(
116-
|| {
117-
assert!(true);
118-
},
119-
false,
120-
);
130+
let catch = try_catch(|| {
131+
assert!(true);
132+
});
121133

122134
assert!(catch.is_ok());
123135
});
@@ -141,24 +153,18 @@ mod tests {
141153
#[should_panic]
142154
fn test_panic() {
143155
Embed::run(|| {
144-
let _ = try_catch(
145-
|| {
146-
panic!("should panic");
147-
},
148-
false,
149-
);
156+
let _ = try_catch(|| {
157+
panic!("should panic");
158+
});
150159
});
151160
}
152161

153162
#[test]
154163
fn test_return() {
155164
let foo = Embed::run(|| {
156-
let result = try_catch(
157-
|| {
158-
return "foo";
159-
},
160-
false,
161-
);
165+
let result = try_catch(|| {
166+
return "foo";
167+
});
162168

163169
assert!(result.is_ok());
164170

@@ -172,17 +178,14 @@ mod tests {
172178
fn test_memory_leak() {
173179
let mut ptr = null_mut();
174180

175-
let _ = try_catch(
176-
|| {
177-
let mut result = "foo".to_string();
178-
ptr = &mut result;
181+
let _ = try_catch(|| {
182+
let mut result = "foo".to_string();
183+
ptr = &mut result;
179184

180-
unsafe {
181-
bailout();
182-
}
183-
},
184-
false,
185-
);
185+
unsafe {
186+
bailout();
187+
}
188+
});
186189

187190
// Check that the string is never released
188191
let result = unsafe { &*ptr as &str };

tests/module.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
11
#![cfg_attr(windows, feature(abi_vectorcall))]
2+
#![cfg(feature = "embed")]
23
extern crate ext_php_rs;
34

4-
#[cfg(feature = "embed")]
55
use ext_php_rs::embed::Embed;
6-
#[cfg(feature = "embed")]
76
use ext_php_rs::ffi::zend_register_module_ex;
87
use ext_php_rs::prelude::*;
98

109
#[test]
11-
#[cfg(feature = "embed")]
1210
fn test_module() {
1311
Embed::run(|| {
1412
// Allow to load the module

tests/sapi.rs

Lines changed: 13 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,19 @@
11
#![cfg_attr(windows, feature(abi_vectorcall))]
2+
#![cfg(feature = "embed")]
23
extern crate ext_php_rs;
34

4-
#[cfg(feature = "embed")]
5-
use std::ffi::c_char;
6-
#[cfg(feature = "embed")]
75
use ext_php_rs::builders::SapiBuilder;
8-
#[cfg(feature = "embed")]
96
use ext_php_rs::embed::{ext_php_rs_sapi_startup, Embed};
10-
#[cfg(feature = "embed")]
117
use ext_php_rs::ffi::{
128
php_module_shutdown, php_module_startup, php_request_shutdown, php_request_startup,
139
sapi_shutdown, sapi_startup, ZEND_RESULT_CODE_SUCCESS,
1410
};
1511
use ext_php_rs::prelude::*;
16-
#[cfg(feature = "embed")]
17-
use ext_php_rs::zend::try_catch;
12+
use ext_php_rs::zend::try_catch_first;
13+
use std::ffi::c_char;
1814

19-
#[cfg(feature = "embed")]
2015
static mut LAST_OUTPUT: String = String::new();
2116

22-
#[cfg(feature = "embed")]
2317
extern "C" fn output_tester(str: *const c_char, str_length: usize) -> usize {
2418
let char = unsafe { std::slice::from_raw_parts(str as *const u8, str_length) };
2519
let string = String::from_utf8_lossy(char);
@@ -34,7 +28,6 @@ extern "C" fn output_tester(str: *const c_char, str_length: usize) -> usize {
3428
}
3529

3630
#[test]
37-
#[cfg(feature = "embed")]
3831
fn test_sapi() {
3932
let mut builder = SapiBuilder::new("test", "Test");
4033
builder = builder.ub_write_function(output_tester);
@@ -58,26 +51,23 @@ fn test_sapi() {
5851

5952
assert_eq!(result, ZEND_RESULT_CODE_SUCCESS);
6053

61-
let _ = try_catch(
62-
|| {
63-
let result = Embed::eval("$foo = hello_world('foo');");
54+
let _ = try_catch_first(|| {
55+
let result = Embed::eval("$foo = hello_world('foo');");
6456

65-
assert!(result.is_ok());
57+
assert!(result.is_ok());
6658

67-
let zval = result.unwrap();
59+
let zval = result.unwrap();
6860

69-
assert!(zval.is_string());
61+
assert!(zval.is_string());
7062

71-
let string = zval.string().unwrap();
63+
let string = zval.string().unwrap();
7264

73-
assert_eq!(string.to_string(), "Hello, foo!");
65+
assert_eq!(string.to_string(), "Hello, foo!");
7466

75-
let result = Embed::eval("var_dump($foo);");
67+
let result = Embed::eval("var_dump($foo);");
7668

77-
assert!(result.is_ok());
78-
},
79-
true,
80-
);
69+
assert!(result.is_ok());
70+
});
8171

8272
unsafe {
8373
php_request_shutdown(std::ptr::null_mut());

0 commit comments

Comments
 (0)