Hi I found this email in PHP.net as a contact address for Web masters.
My question is about PHP SAPI C/C++ development.
I’ve successfully attached PHP to my C/C++ application as a SAPI module
with libphp.so , and it’s working now , but I have a problem with multiple
tasks in my application.
I need to execute PHP code in some thread of my application and continue
excecution in another. Is is possible to somehow get all global PHP core
hashtables from first thread and restore PHP from that point in another
thread using that hashtables with all generated variables and functions ?
Please provide some information about how this could be possible.
Thanks.
Hi,
I need to execute PHP code in some thread of my application and continue
excecution in another. Is is possible to somehow get all global PHP core
hashtables from first thread and restore PHP from that point in another
thread using that hashtables with all generated variables and functions ?
PHP works request base. Meaning the idea is to have isolated
shared-nothing requests.
PHP can run in two modes:
1. In a global environment, or
2. in a threaded environment
this is controlled by enabling or disabling ZTS - zend thread safety /
TSRM thread-safe resource manager. In the first case you have a global
state running one "request" at a time, theoretically this single request
context can be accessd by multiple threads while access has to be
guarded by some mutex.
In the second case you can have multiple requests which separate state.
Each of those is bound to a (posix|windows) thread sharing a context in
this mode between different threads can't be easily done and requires
patching (in non-public code I once created worker threads owning the
PHP request and different threads can signal there to bypass, but that's
a mess).
The probably most simple SAPI using different threads is my pconn SAPI:
https://github.com/johannes/pconn-sapi
Except for source we don't really have good documentation on all the
details. So please try to go through different SAPIs and try to
understand them. Specific questions are welcome on this list.
johannes
How about writing this logic in an extension? Because u can write your own RSHUTDOWN function to protect your data.
sorry for my poor english.
--
lanxiaolu
在 2014年11月20日,下午6:30,Johannes Schlüter johannes@schlueters.de 写道:
Hi,
I need to execute PHP code in some thread of my application and continue
excecution in another. Is is possible to somehow get all global PHP core
hashtables from first thread and restore PHP from that point in another
thread using that hashtables with all generated variables and functions ?PHP works request base. Meaning the idea is to have isolated
shared-nothing requests.PHP can run in two modes:
1. In a global environment, or 2. in a threaded environment
this is controlled by enabling or disabling ZTS - zend thread safety /
TSRM thread-safe resource manager. In the first case you have a global
state running one "request" at a time, theoretically this single request
context can be accessd by multiple threads while access has to be
guarded by some mutex.
In the second case you can have multiple requests which separate state.
Each of those is bound to a (posix|windows) thread sharing a context in
this mode between different threads can't be easily done and requires
patching (in non-public code I once created worker threads owning the
PHP request and different threads can signal there to bypass, but that's
a mess).The probably most simple SAPI using different threads is my pconn SAPI:
https://github.com/johannes/pconn-sapiExcept for source we don't really have good documentation on all the
details. So please try to go through different SAPIs and try to
understand them. Specific questions are welcome on this list.johannes
How about writing this logic in an extension? Because u can write
your own RSHUTDOWN function to protect your data.
Sorry, I have no idea what logic you want to put in a rshutdown and what
data you want to protect. And how that relates to this discussion around
SAPIs.
johannes
Thanks for your responses.
I saw pconn-sapi it's very similar threaded example that I want to
implement.
I've crated non blocking Event loop in my C++ application ( it's high load
binary API server ) , and now I'm trying to integrate PHP SAPI for writing
some customisable scripts using PHP functions.
My app starting PHP SAPI with function php_embed_init(argc, argv PTSRMLS_CC);
and it stays alive always , because it will take some preference from my
app if I'll start and end PHP SAPI on every PHP script parsing or function
call.
And based on that now my main problem is that in PHP C++ sources there are
a lot of static, global variables which is not useful for me, to clean that
all for every request .... So I'm wondering to build something which will
help to somehow "save current state" of PHP SAPI , and continue it on every
request from saved source, without sharing any variable between multiple
requests.
Let me know if you didn't get my idea.
Now I'm trying to do this thing for my Startup project, but I'll share it
over GitHub if I'll have some success :)
Thanks.
2014-11-20 15:34 GMT+04:00 Johannes Schlüter johannes@schlueters.de:
How about writing this logic in an extension? Because u can write
your own RSHUTDOWN function to protect your data.Sorry, I have no idea what logic you want to put in a rshutdown and what
data you want to protect. And how that relates to this discussion around
SAPIs.johannes
And based on that now my main problem is that in PHP C++ sources there
are a lot of static, global variables which is not useful for me, to
clean that all for every request .... So I'm wondering to build
something which will help to somehow "save current state" of PHP
SAPI , and continue it on every request from saved source, without
sharing any variable between multiple requests.
If you need to cleanup things between requests php_request_[startup|
shutdown] are the functions you need which will do that.
Basic flow in pseudocode with reference to pconn functions doing a bit
more:
/* once on application start, see also pconn_init_php() */
sapi_startup();
/* for each request, see pconn_do_request() /
while (!program_end()) {
/ start request context */
php_request_startup(TSRMLS_C);
/* we can multiple scripts in one request context */
while (get_script_for_current_request()) {
if (source_is_in_a_file()) {
php_execute_script(file_handle TSRMLS_CC);
} else if (source_is_in_a_string()) {
zend_eval_String();
}
}
/* clean up everything related to the request */
php_request_shutdown((void *) 0);
}
/* at the end of the application shutdown completely */
php_module_shutdown(TSRMLS_C);
sapi_shutdown();
Now this uses global state. If you need multiple states parallel compile
PHP in threaded mode (--enable-maintainer-zts manually at config time or
force it by PHP_BUILD_THREAD_SAFE in your SAPI's custom config.m4. In
that mode PHP globals which are request-specific (i.e. everything that
happens in the while (!program_end()) loop) are bound to a windows
thread or pthread (depending on platform). So if your event based system
needs multiple PHP requests in parallel it has to create enough threads
and route PHP work there. Handling multiple requests from a single
thread in parallel is not supported from PHP's architecture (if you like
adventures you might try to hack this by looking at tsrm_thread_id in
TSRM/TSRM.c but that's not really a good way.
Another approach is not embedding PHP directly in your process (which is
dangerous anyways - PHP might crash due to stack overflow on some
recursion patterns etc. which would kill your complete server) but by
calling external PHP processes via FastCGI or FPM protocols, just like
nginx or others do.
johannes