Reputation:
I need to multithread a php function but when I call a php function I get this error "Safari Can’t Open the Page"
Safari can’t open the page “localhost/home.php” because the server unexpectedly dropped the connection. This sometimes occurs when the server is busy. Wait for a few minutes, and then try again.
I have this lines in my php file
<?php
echo "Hello World","<br>";
open_thread("hello");
function hello() {
echo "Hello World";
}
When I remove hello
from open_thread("hello");
, it simply outputs this warning:
Warning: open_thread() expects exactly 1 parameter, 0 given in /Users/username/Sites/home.php on line 3
This also happens when I call C function which has output in it, when I remove outputs from the function server works and displays nothing.
The problem occurs here pthread_join(tid, NULL);
Here is my C codes
PHP_FUNCTION(open_thread)
{
zval *threaded_func;
zend_string *func_name;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &threaded_func) != SUCCESS) {
return;
}
if (Z_TYPE_P(threaded_func) != IS_NULL)
{
if (!zend_is_callable(threaded_func, 0, &func_name TSRMLS_CC))
{
php_error_docref(NULL TSRMLS_CC, E_WARNING, "’%s’ is not a valid read callback", func_name);
efree(func_name);
RETURN_FALSE;
}
efree(func_name);
}
pthread_t tid;
zend_printf("Starting..\n");
pthread_create(&tid, NULL, (void *) threaded_func, NULL);
pthread_join(tid, NULL);
zend_printf("Finished\n");
}
The Question
Is it a thread safe issue? how do I fix it?
Upvotes: 1
Views: 393
Reputation: 17168
PHP can be built to support multi threaded SAPI's - ZTS mode - however, it's important to realize that the memory model used is share nothing.
In a shared nothing model, each thread has a different interpreter (compiler, executor, all module globals, all user code, the whole lot).
This means various things:
pass_two
and execute the copy of the code.Simply starting a thread and attempting to call into Zend is doomed to fail, as it ignores the shared nothing nature of PHP.
The flow of new threads needs to be something like:
void routine(void *thing) {
ts_resource(0);
php_request_startup();
/* do stuff */
php_request_shutdown();
ts_free_thread();
}
ts_resource
: this initializes TSRM in the new thread, in turn initializing some of Zendphp_request_startup
: initializes the rest of everything, among other things runs RINIT
for all modulesphp_request_shutdown
: this runs RSHUTDOWN
, generally cleans upts_free_thread
: optionally free, would otherwise happen at process shutdown (when TSRM is finally shutdown)As it is, the example flow would also fail, if it tries to call user code compiled by (for) another thread: After request startup and before you can call user code you need to copy the code into the current context first.
The fine detail of how any of this works in the real world can be found in the pthreads extension sources.
Upvotes: 1