-
Notifications
You must be signed in to change notification settings - Fork 147
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
Zend Abstract Interface: Method call seam (PHP 5) #1186
Conversation
6528aa6
to
13e9614
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Love to see this coming 😄
932fe70
to
49b0ec6
Compare
49b0ec6
to
766a401
Compare
766a401
to
732eced
Compare
732eced
to
954dd6f
Compare
954dd6f
to
6293b4e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am unable to build the project for PHP 5.6-debug, though I don't think the debug part is affecting it. CMake is unable to locate libphp5.so
. This makes sense to me, because that's an artifact of the embed SAPI, which I didn't build:
/opt/php/5.6-debug/bin/php-config --php-sapis
cli fpm phpdbg cgi
However, I thought using zai
meant we no longer needed the embed SAPI?
The embed SAPI is only required to run the tests with the ZAI SAPI. Although we don't use the embed SAPI directly, ZAI SAPI requires access to the PHP shared object which, as you mentioned, is only built when the embed SAPI is enabled. So the embed SAPI is required to run the tests. Ideally we should be able to build PHP with a config flag like |
ebf6fca
to
6bbb941
Compare
zai_sandbox sandbox; | ||
zai_sandbox_open(&sandbox); | ||
|
||
zend_try { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Couldn't this be a problem if we catch bailouts in tracing closure callbacks? I assume bailouts happen because they can't recover, so does this need to "re-throw" the bailout? I'm thinking about ext/soap
or something. I don't know, we don't intend to call any such functions, do we? Does exit
use bailout on these versions?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hum. I think you're right that we cannot safely catch arbitrary zend_bailouts and go on pretending like nothing happened. In the ext/soap
case, zend_bailouts are caught and converted into exceptions, but as you pointed out that's not the case for exit
. (In PHP 8 exit
is a clean shutdown thanks to the uncatchable Chuck Norris exception, UnwindExit
. 😄) But we can expect an arbitrary unclean shutdown here when exit
is used or some fatal error. If we ignored it, this would lead to a lot of ZMM leaks and likely a number of real memory leaks.
So although it is technically a "hole in the sandbox" to remove the zend_try
here, it's actually safer to not catch them. If we wanted a true sandbox, we could run these as "sub requests" like ext/sandbox
does. But I'm not sure the overhead of something like this would be worth it - especially since we're reducing our C-to-PHP seams.
Very nice catch on this (pun intended). I'll remove this and update the tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need to remove it, or do we need to catch it, undo the sandbox and then re-throw?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, 👆 that. 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This has been addressed in ff1823c.
* Methods cannot be called outside of a request context so this MUST be called | ||
* from within a request context (after RINIT and before RSHUTDOWN). A crash | ||
* will occur if this is called outside of a request context. | ||
*/ | ||
bool zai_call_method_without_args_ex(zval *object, const char *method, size_t method_len, zval **retval TSRMLS_DC); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we properly detect request context and return false if we're not inside one? Then we can run tests since they won't crash. If this is too expensive then we can consider moving it to debug-only or something.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea. I've aded this check in e346b91. I believe this only applies to static method calls since a crash will occur when trying to instantiate an object outside of a request context. So I updated the formally crashy test to a static method call test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for addressing my concerns. I'm glad that you documented many of the sharp edges so we know why the code is written that way; this was something sorely needed.
Thanks for such a high quality code review @morrisonlevi. 💯 |
Description
The Zend Abstract Interface (ZAI) is an API for calling into PHP from C. The seams are decoupled from the main PHP tracer and tested using the ZAI SAPI.
This PR includes the first ZAI seam on PHP 5 for safely calling methods (sandboxed):
zai_class_lookup()
zai_call_method_without_args()
zai_call_static_method_without_args()
This seam will be used to finish the implementation of autoflushing in #1189.
Readiness checklist
Reviewer checklist