-
Notifications
You must be signed in to change notification settings - Fork 67
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
constructing exceptions in rust #203
Comments
Yeah, inheritance doesn't work ATM... |
i don't think this is related to inheritance, the however, exceptions are different from normal classes, they need more context ( file, line, trace ), as i said, throwing and catching works, zend will make sure to construct the exception correctly, but it is slow, we need to look at how zend constructs an exception, and basically do the same, so that this will allow us to be able to construct ext-php-rs exceptions without throwing them. this is something that a lot of PHP libraries do, to give you an example: while throwing immediately from |
correction: the fn get_constructor() -> option {
constructor = none;
if ce.constructor == null {
traits = ce.traits;
for trait in traits {
if trait.has_constructor() {
constructor = trait.get_constructor();
break;
}
}
if constructor.is_none() {
if ce.parent != null {
// we do the same for the parent
return get_constructor(ce.parent);
}
}
} else {
constructor = some(ce.constructor);
}
constructor
} |
I think the reason why there's no backtrace is that you might be trying to construct an exception outside of a VM stack frame (when |
no, that's not the issue, if there's no stack frame, we would get an error. see: https://heap.space/xref/php-src/Zend/zend_exceptions.c?r=45e224cf#205 we are missing something else that i still can't figure out :) |
You would have an error if the exception is thrown without a stack frame, not when constructing the exception object, see https://heap.space/xref/php-src/Zend/zend_exceptions.c?r=45e224cf#244. |
throwing it doesn't result in an error, if you try the code above an call do |
Mmm okay... have you tried to assert that |
no, but i don't think that would change anything, as in my test script, the file looks exactly like this: <?php
function foo() {
return Psl\Channel\Exception\ClosedChannelException::forSending();
}
function bar() {
throw foo();
}
function baz() {
bar();
}
baz(); meaning it is not not possible for another exception to be present. |
There's a discord channel that is more appropriate for these kind of lengthy discussions: https://discord.com/channels/115233111977099271/829877152048349266 |
for anyone reading this thread, until this issue is resolved, here's how you can create your own exceptions: use ext_php_rs::convert::IntoZvalDyn;
use ext_php_rs::error::Result;
use ext_php_rs::ffi;
use ext_php_rs::types::Zval;
use ext_php_rs::zend::ClassEntry;
pub unsafe fn make_exception(
class: Option<&'static ClassEntry>,
arguments: Vec<&dyn IntoZvalDyn>,
) -> Result<Zval> {
let class = class.unwrap();
let len = arguments.len();
let arguments = arguments
.into_iter()
.map(|val| val.as_zval(false))
.collect::<Result<Vec<_>>>()?
.into_boxed_slice();
let class_ptr = class as *const _ as *mut _;
let constructor_ptr = class.constructor;
let object = class.__bindgen_anon_2.create_object.unwrap()(class_ptr);
ffi::zend_call_known_function(
constructor_ptr,
object,
class_ptr,
std::ptr::null_mut(),
len as _,
arguments.as_ptr() as _,
std::ptr::null_mut(),
);
let object = object
.as_mut()
.expect("error: failed to allocate memory for object");
let mut result = Zval::new();
result.set_object(object);
Ok(result)
} Note: this is not 100% guaranteed to work, if you found an issues with it, let us know :) let exception = unsafe { make_exception(MY_EXCEPTION_CE, vec![&message]).unwrap() }; |
I have been struggling trying to implement the following:
I tried the following:
this results in an error when calling
FooException::from_bar()
( trying to call non-static method statically ).i tried making
from_bar()
into a function, but this also didn't work, as non of the exception properties were initialized, the exception will always not have a backtrace, ( file being""
, and line being0
)I initially tried to create the object and call it's constructor:
this one works, but it's the same as before, backtrace is completely missing, while it works perfectly for "normal" classes, it fails for Exceptions, i believe there's a zend function that i should call on the exception object before/after constructing it, but i can't find it ( yet ) in the ZEND API.
So the solution i found, is the following, which is extremely slow:
any help would be appreciated :)
The text was updated successfully, but these errors were encountered: