All,
I've searched the web for this answer and I'm stumped. I can't find
the answers. So I thought I'd try the lists. Here goes:
I have seen how to embed PHP 5 using the code like:
...
php_embed_module.ub_write = my_ub_write_func;
php_embed_module.log_message = my_log_func;
php_embed_module.sapi_error = my_error_log;
...
zend_eval_string(...);
...
And from this, I looked in the code to see that php_embed_module is a
static variable that's used in the initialization methods so it seems
as though this can't possibly be thread-safe.
Yet web servers do it all the time.
I read on the web that the global variables for the PHP engine are
maintained in the thread where they were originally defined. This leads
me to believe that there's the possibility that the php_embed_module
and other important variables might be thread-local storage, and
therefore thread-safe.
Yet if that were the case, how does one define different write, log,
and error functions so that the engine of one thread does not interfere
with another?
In general, my problem is this:
I have a multi-threaded C++ app that I want to embed the PHP 5 engine
into. I have read up how to create extensions to PHP, and will do that
as necessary, but I need to be able to call this engine from my code
and capture stdout, stderr, etc.
Can I do this with PHP 5.0.3 as it exists now?
Are there special things I need to watch out for?
Any pointers, FAQ sites, etc. that I can look at would be most helpful.
Thanks,
Bob (drbob@TheManFromSPUD.com)
The Man from S.P.U.D.
We will write no code before it's designed.
these still need tidying up alot, but the do work.
http://docs.akbkhome.com/php_embed.c.txt
http://docs.akbkhome.com/php_embed.h.txt
replace the code in php_embed with them, make sure you compile with the
zts enabled, and the macros's are similar to the original embed (use
threaded start call at application start up, and thread start /start end
within the pthread_start(...callback..) method
check out php.pecl on #efnet you might get lucky..
Regards
Alan
Bob Beaty wrote:
All,
I've searched the web for this answer and I'm stumped. I can't find
the answers. So I thought I'd try the lists. Here goes:
I have seen how to embed PHP 5 using the code like:... php_embed_module.ub_write = my_ub_write_func; php_embed_module.log_message = my_log_func; php_embed_module.sapi_error = my_error_log; ... zend_eval_string(...); ...
And from this, I looked in the code to see that php_embed_module is a
static variable that's used in the initialization methods so it
seems as though this can't possibly be thread-safe.
Yet web servers do it all the time.
I read on the web that the global variables for the PHP engine are
maintained in the thread where they were originally defined. This
leads me to believe that there's the possibility that the
php_embed_module and other important variables might be thread-local
storage, and therefore thread-safe.
Yet if that were the case, how does one define different write, log,
and error functions so that the engine of one thread does not
interfere with another?In general, my problem is this:
I have a multi-threaded C++ app that I want to embed the PHP 5 engine
into. I have read up how to create extensions to PHP, and will do that
as necessary, but I need to be able to call this engine from my code
and capture stdout, stderr, etc.
Can I do this with PHP 5.0.3 as it exists now?
Are there special things I need to watch out for?
Any pointers, FAQ sites, etc. that I can look at would be most helpful.
these still need tidying up alot, but the do work.
http://docs.akbkhome.com/php_embed.c.txt
http://docs.akbkhome.com/php_embed.h.txt
replace the code in php_embed with them, make sure you compile with the zts
enabled, and the macros's are similar to the original embed (use threaded
start call at application start up, and thread start /start end within the
pthread_start(...callback..) method
Thread safeness is not a problem for a single thread.
The problem is to call user functions from different threads
(tsrm_ls pointed to somewhere in different threads, global
vars etc are not protected).
Which is my concern.
I've looked at the code differences, and it appears that this
modification works for running different source files through the
engine, but I'm concerned about the safety of zend_eval_string() if I
initialize the engine in one thread and then try to have several
threads calling zend_eval_string() on different strings.
I'm not convinced that simply making the php_embed_module thread-local
is going to work either. I'm concerned that the engine was written with
the idea that only one thread can be initializing the php_embed_module
and making calls to zend_eval_string(). If this is the case, then I'd
have to re-write a lot more than php_embed.c to get thread-safety out
of the engine.
Or am I on the wrong track?
Bob
these still need tidying up alot, but the do work.
http://docs.akbkhome.com/php_embed.c.txt
http://docs.akbkhome.com/php_embed.h.txt
replace the code in php_embed with them, make sure you compile with
the zts enabled, and the macros's are similar to the original embed
(use threaded start call at application start up, and thread start
/start end within the pthread_start(...callback..) method
Thread safeness is not a problem for a single thread.
The problem is to call user functions from different threads
(tsrm_ls pointed to somewhere in different threads, global vars etc
are not protected).
Thanks,
Bob (drbob@TheManFromSPUD.com)
The Man from S.P.U.D.
We will write no code before it's designed.
I think derick does something like this in SRM,
but basically if you want to load something in the global thread, and
let the children inherit the data / classes /function etc.
AFAIR you need to serialize the opcodes, and copy them for each thread.
(or use something like bcompiler to load cached opcodes for you..)
Basically the engine does thread saftey by having a seperate data store
for each thread. As far as the engine goes, it treats each thread pretty
much as a seperate process..
There was some code in the threads extension to pass variables between
threads.., cant remember the status of it though.
The code I posted works pretty well, but I include a file as soon as the
new thread starts up, and dont have any thread global data at present.
Regards
Alan
Bob Beaty wrote:
Which is my concern.
I've looked at the code differences, and it appears that this
modification works for running different source files through the
engine, but I'm concerned about the safety of zend_eval_string() if I
initialize the engine in one thread and then try to have several
threads calling zend_eval_string() on different strings.I'm not convinced that simply making the php_embed_module thread-local
is going to work either. I'm concerned that the engine was written
with the idea that only one thread can be initializing the
php_embed_module and making calls to zend_eval_string(). If this is
the case, then I'd have to re-write a lot more than php_embed.c to get
thread-safety out of the engine.Or am I on the wrong track?
Bob
these still need tidying up alot, but the do work.
http://docs.akbkhome.com/php_embed.c.txt
http://docs.akbkhome.com/php_embed.h.txt
replace the code in php_embed with them, make sure you compile with
the zts enabled, and the macros's are similar to the original embed
(use threaded start call at application start up, and thread start
/start end within the pthread_start(...callback..) methodThread safeness is not a problem for a single thread.
The problem is to call user functions from different threads
(tsrm_ls pointed to somewhere in different threads, global vars etc
are not protected).Thanks, Bob (drbob@TheManFromSPUD.com) The Man from S.P.U.D. We will write no code before it's designed.
I think derick does something like this in SRM,
but basically if you want to load something in the global thread, and let
the children inherit the data / classes /function etc.
AFAIR you need to serialize the opcodes, and copy them for each thread. (or
use something like bcompiler to load cached opcodes for you..)
For me, inter-threads variables api is working (separated table, holding
references between threads; must be synched by mutexes).
it will take some time to make that available...
ZTS enabled PHP has "strong thread affinity".
Calls into the engine are thread-safe provided that you have
previously initialized the engine on that thread.
Note that you should not efree() memory allocated on one thread from
outside of that thread, on pain of segfault. eg: resources from one
thread cannot be safely passed on to another thread.
--Wez.
Which is my concern.
I've looked at the code differences, and it appears that this
modification works for running different source files through the
engine, but I'm concerned about the safety of zend_eval_string() if I
initialize the engine in one thread and then try to have several
threads calling zend_eval_string() on different strings.I'm not convinced that simply making the php_embed_module thread-local
is going to work either. I'm concerned that the engine was written with
the idea that only one thread can be initializing the php_embed_module
and making calls to zend_eval_string(). If this is the case, then I'd
have to re-write a lot more than php_embed.c to get thread-safety out
of the engine.Or am I on the wrong track?
Bob
these still need tidying up alot, but the do work.
http://docs.akbkhome.com/php_embed.c.txt
http://docs.akbkhome.com/php_embed.h.txt
replace the code in php_embed with them, make sure you compile with
the zts enabled, and the macros's are similar to the original embed
(use threaded start call at application start up, and thread start
/start end within the pthread_start(...callback..) method
Thread safeness is not a problem for a single thread.
The problem is to call user functions from different threads
(tsrm_ls pointed to somewhere in different threads, global vars etc
are not protected).
Thanks,
Bob (drbob@TheManFromSPUD.com)
The Man from S.P.U.D.
We will write no code before it's designed.
Wez,
OK, I'm with you on this so far, but how do you differentiate
ub_write, log_message, and sapi_error on different threads? It would
seem to me that you'd need to have different functions for each thread
as the calls to ub_write don't include some indication of the thread
that this is being called under.
Then again, maybe it's in the php_embed_module if it's tightly bound
to the thread... For example, if I set the title in the thread-bound
php_embed_module to something specific for each thread then check that
within the call to ub_write() I can see who this 'write' belongs to.
If I'm missing the boat on these function callbacks, or there's an
easier way to capture stdout, stderr, etc. in a ZTS-enabled PHP/Zend
environment, please let me know.
I'm sorry if I seem a bit dense, but I'm trying to figure things out
and design the code before I start writing it.
Bob
ZTS enabled PHP has "strong thread affinity".
Calls into the engine are thread-safe provided that you have
previously initialized the engine on that thread.Note that you should not efree() memory allocated on one thread from
outside of that thread, on pain of segfault. eg: resources from one
thread cannot be safely passed on to another thread.--Wez.
On Mon, 28 Feb 2005 14:24:05 -0600, Bob Beaty drbobbeaty@gmail.com
wrote:Which is my concern.
I've looked at the code differences, and it appears that this
modification works for running different source files through the
engine, but I'm concerned about the safety of zend_eval_string() if I
initialize the engine in one thread and then try to have several
threads calling zend_eval_string() on different strings.I'm not convinced that simply making the php_embed_module thread-local
is going to work either. I'm concerned that the engine was written
with
the idea that only one thread can be initializing the php_embed_module
and making calls to zend_eval_string(). If this is the case, then I'd
have to re-write a lot more than php_embed.c to get thread-safety out
of the engine.Or am I on the wrong track?
Bob
these still need tidying up alot, but the do work.
http://docs.akbkhome.com/php_embed.c.txt
http://docs.akbkhome.com/php_embed.h.txt
replace the code in php_embed with them, make sure you compile with
the zts enabled, and the macros's are similar to the original embed
(use threaded start call at application start up, and thread start
/start end within the pthread_start(...callback..) method
Thread safeness is not a problem for a single thread.
The problem is to call user functions from different threads
(tsrm_ls pointed to somewhere in different threads, global vars etc
are not protected).
Thanks,
Bob (drbob@TheManFromSPUD.com)
The Man from S.P.U.D.
We will write no code before it's designed.
Thanks,
Bob (drbob@TheManFromSPUD.com)
The Man from S.P.U.D.
We will write no code before it's designed.
The TSRMLS_DC magic parameter passes around the thread-local storage
pointer for the thread; the SG() macro uses that information to get
at the sapi_globals struct for your thread.
You can also stuff your own SAPI related information into
SG(server_context), if you are writing a SAPI:
... in my thread init code ...
struct my_globals *g = calloc(1, sizeof(*g));
SG(server_context) = g;
... in the ub write callback ...
struct my_globals g = (struct my_globals)SG(server_context);
If TSRMLS_DC is not present in the function declaration, you can use
TSRMLS_FETCH() to summon it out of thread-local-storage.
--Wez.
Wez,
OK, I'm with you on this so far, but how do you differentiate
ub_write, log_message, and sapi_error on different threads? It would
seem to me that you'd need to have different functions for each thread
as the calls to ub_write don't include some indication of the thread
that this is being called under.
Then again, maybe it's in the php_embed_module if it's tightly bound
to the thread... For example, if I set the title in the thread-bound
php_embed_module to something specific for each thread then check that
within the call to ub_write() I can see who this 'write' belongs to.
If I'm missing the boat on these function callbacks, or there's an
easier way to capture stdout, stderr, etc. in a ZTS-enabled PHP/Zend
environment, please let me know.
I'm sorry if I seem a bit dense, but I'm trying to figure things out
and design the code before I start writing it.Bob
ZTS enabled PHP has "strong thread affinity".
Calls into the engine are thread-safe provided that you have
previously initialized the engine on that thread.Note that you should not efree() memory allocated on one thread from
outside of that thread, on pain of segfault. eg: resources from one
thread cannot be safely passed on to another thread.--Wez.
On Mon, 28 Feb 2005 14:24:05 -0600, Bob Beaty drbobbeaty@gmail.com
wrote:Which is my concern.
I've looked at the code differences, and it appears that this
modification works for running different source files through the
engine, but I'm concerned about the safety of zend_eval_string() if I
initialize the engine in one thread and then try to have several
threads calling zend_eval_string() on different strings.I'm not convinced that simply making the php_embed_module thread-local
is going to work either. I'm concerned that the engine was written
with
the idea that only one thread can be initializing the php_embed_module
and making calls to zend_eval_string(). If this is the case, then I'd
have to re-write a lot more than php_embed.c to get thread-safety out
of the engine.Or am I on the wrong track?
Bob
these still need tidying up alot, but the do work.
http://docs.akbkhome.com/php_embed.c.txt
http://docs.akbkhome.com/php_embed.h.txt
replace the code in php_embed with them, make sure you compile with
the zts enabled, and the macros's are similar to the original embed
(use threaded start call at application start up, and thread start
/start end within the pthread_start(...callback..) method
Thread safeness is not a problem for a single thread.
The problem is to call user functions from different threads
(tsrm_ls pointed to somewhere in different threads, global vars etc
are not protected).
Thanks,
Bob (drbob@TheManFromSPUD.com)
The Man from S.P.U.D.
We will write no code before it's designed.Thanks, Bob (drbob@TheManFromSPUD.com) The Man from S.P.U.D. We will write no code before it's designed.
ZTS enabled PHP has "strong thread affinity".
Calls into the engine are thread-safe provided that you have
previously initialized the engine on that thread.
Hm...
The problem is when we create a thread and call_user_function for the
function from the parent thread.
Which is my concern.
I've looked at the code differences, and it appears that this modification
works for running different source files through the engine, but I'm
concerned about the safety of zend_eval_string() if I initialize the engine
in one thread and then try to have several threads calling zend_eval_string()
on different strings.
It will not work, as I can see.
It works fine, when I do some preparations, like:
thr=pthread_self();
tsrml=ts_resource_ex(0, &thr);
php_request_startup(tsrml);
zend_eval_string("
But, I must note, that there are no waits for the "thread to start
current thread" in the parent thread in my situation.
Maybe, the code above is not correct (I'm new to PHP's internals), but it
works correctly.
I'm not convinced that simply making the php_embed_module thread-local is
going to work either. I'm concerned that the engine was written with the idea
that only one thread can be initializing the php_embed_module and making
calls to zend_eval_string(). If this is the case, then I'd have to re-write a
lot more than php_embed.c to get thread-safety out of the engine.
Or am I on the wrong track?
Imagine, we have (usually) situation, when we are running a function in a
separate thread (such idea is partially realized in pecl/threads).
So, if there are several threads working with one parsed script, we need
to provide a kind of task context for each thread + mechanics for
sync/async methods.
...maybe, I'm on the wrong track.... :)
How do I select an appropriate LOGO_GUID?
-- Dale