PHP pThreads IIS: unexpected output in browser - php

I'm attempting to have a php script run multi-threaded using PHP pThreads in a IIS 7 PHP 5.6 x86 (thread safe) environment. I've created a github issue but I haven't heard back and though some other coders here may have experienced the same problem.
PHP is running fine and scripts which don't require pThreads execute like normal. However when I add some multi-threaded code to my script, only the block of code which is non-multithreaded executes in the browser unless I call phpinfo before executing the code. For example:
<?php
class AsyncOperation extends Thread {
public function run(){
echo 'hello world';
}
}
$thread = new AsyncOperation();
if($thread->start()) {
$thread->join();
}
?>
Has no output in the browser (still a response code of 200 though).
But the following code with phpinfo called first works:
<?php
phpinfo();
class AsyncOperation extends Thread {
public function run(){
echo 'hello world';
}
}
$thread = new AsyncOperation();
if($thread->start()) {
$thread->join();
}
?>
The expected output of all of the phpinfo content, and then hello world is there. I've also noticed that sending phpinfo(64) does not echo hello world, but all of the other valid parameters for phpinfo cause hello world to be printed.
I've also tried running the original (without phpinfo) script from the command line and noticed that "hello world" is echoed in the console. Which leads me to believe this is an IIS7 misconfiguration but that doesn't explain how calling phpinfo would make it work?
Also I should note, there's nothing in the error logs either, and the system is set to log all errors.

As krakjoe mentioned in your issue, strange things can happen when different threads work with the same output buffer.
It's probably best to follow JakeFalcor's advice and first store the thread's output in memory and then echo it from the main thread.
class AsyncOperation extends Thread {
public $output;
public function run(){
$this->output = 'hello world';
}
}
$thread = new AsyncOperation();
if($thread->start()) {
$thread->join();
echo $thread->output;
}
See also: ob_start()

Related

How to run Magento shell script in browser

This question has been asked a few times but none of them solves my issue.
I simply created a file:
/shell/test.php
<?php
require_once 'abstract.php';
class Mage_Shell_Test extends Mage_Shell_Abstract
{
public function run() {
echo 'in-shell-test!';
}
}
$shell = new Mage_Shell_Test();
$shell->run();
and commented out $this->_validate(); in
/shell/abstract.php
Then I still see the page of WHOOPS, OUR BAD...
Appreciate any ideas.
You could override the _validate method which is inherited from Mage_Shell_Abstract. This method checks where you are running your script from and it looks like this:
protected function _validate()
{
if (isset($_SERVER['REQUEST_METHOD'])) {
die('This script cannot be run from Browser. This is the shell script.');
}
}
You can change this to return true, but this validation was obviously put there for a reason. If you plan on leaving the script there for a longer period, I would recommend looking for a different approach.

Calling a Python script from PHP using Multi-threading

I'm using PHP to display the Python output in the browser. Since the Python script takes a long time to print the output, The User Interface gets hung till the Python script finishes its execution.
Pthreads for Windows is enabled in PHP for multithreading the shell_exec( ) function which invokes the Python script. Inspite of using Pthreads, the User Interface still gets hung.
Here is the code:
$output_customer_churn_prediction = "";
class WorkerThreads extends Thread {
private $workerId;
public function __construct($id)
{
$this->workerId = $id;
}
public function run()
{
sleep(rand(0, 3));
echo "Worker {$this->workerId} ran" . PHP_EOL;
$output_customer_churn_prediction = shell_exec('python '.$_SERVER['DOCUMENT_ROOT'].'/analytics/python/neural-net-prediction-customer-attrition.py');
print_r($output_customer_churn_prediction);
}
}
$workers[0] = new WorkerThreads(0);
$workers[0]->start();
print_r($output_customer_churn_prediction, true);
Even with multithreading, the User Interface (generated by PHP) gets hung while invoking the Python Neural Net script.
What could be the reason ?
PHP is caching the Output. You Need to deactivate the Output cache. Then your Browser will not hang.
See ob_flush()

Laravel console command catch signal from terminal

I'm trying to catch signals in terminal. I know that I can use pcntl_signal() function but it doesn't work for me.
I am trying with this code:
public function handle() {
pcntl_signal(SIGINT, function ($signo) {
echo "CATCH!\n";
exit;
});
while (true) { echo("!\n"); sleep(2); }
}
When I press Ctrl+C I don't see any result, because program still is working. What do I wrong?
I want to stop program after press Ctrl+C and call __destruct() method.
The pcntl_signal() function won't work without this line in your file:
declare(ticks = 1);
It should probably be at the top of the file, before the class definition.
A tick is an event that occurs regularly during the program execution, and in this case each tick triggers the program to check the signals coming in. I think. I don't know why it's not enabled by default, possibly due to increased CPU load while it's in operation?
I've seen some assertions that ticks were deprecated after PHP 5.3, but I just tested in PHP 7.0.9 and can confirm that pcntl_signal() doesn't work without it.
This can be done with the Laravel SignalableCommandInterface now
class MyCommand extends Command implements SignalableCommandInterface
{
public function handleSignal(int $signal): void
{
echo "CATCH!\n";
exit;
}
// Which signals will be handled
public function getSubscribedSignals(): array
{
return [SIGINT, SIGTERM];
}
}

PHP Built-In Server Exiting with SIGSEGV / Wordpress

Developing a wordpress blog locally, my PHP server is dying with SIGSEGV half-way through rendering the page.
Here's my startup script: sudo php -S 127.0.0.1:80 -t ../reece-blog-local
I wish I could provide more details, but I can't seem to get any information out of PHP about this. The only reason I know it's exiting with SIGSEGV is that I'm running this process with foreman, otherwise the process just exits silently.
There does not seem to be a particular line of code that's making it break, I can track down the area of the error based on the HTML that's managed to render before exit, and I can stick in a few echo "Hello, world!"s and it breaks on any given one of them.
Notes:
server was working fine until I upgraded to Mavericks, so thinking that something there could be interfering.
confirmed this happens when CURLing any URL, so likely rules out this being an issue with serving static files.
not exhausting my memory limit
How can I further debug this issue, in lieu of any specific errors output by PHP?
PHP server will exit with segmentation fault (SIGSEGV) error in the event of infinite recursion, e.g.:
function test() {
test();
}
If the output is buffered and you use echo to debug an error like this, the error may appear to occur in strange places (hence why it would seem to break on a line like echo "Hello, world!";)
Instead, you can use error_log($yourMessage, 4); to output a message to the console. This helped track down the error for me (though from reading around it seems XDebug may be the preferred solution for finding errors like this.)
For what it's worth, here's effectively how I had infinite recursion:
class TheParent {
public function __call($method, $args) {
return call_user_func_array(array($this, $method), $args);
}
}
class TheChild extends TheParent {
protected function thisIsOkay() {
echo 'yay';
}
private function sigsegv() {
echo 'no';
}
}
$c = new TheChild;
$c->thisIsOkay();
$c->sigsegv();
If we attempt to call a private function in TheChild, __call will be invoked, attempt to access the private function, invoking __call, etc.

Storing closures in thread fails

I'm trying to use a closure as a callback once a thread is done running. However I'm running into what seems to be a limit/failure of PHP or the pthread extension.
My dev stack is running on Win7 x64 with PHP 5.5.3 x86 TS, pthread version 0.44.
The following code works :
class Test
{
public $callbackVar;
}
$test = new Test();
$callbackVar = function()
{
echo "Callback var invoked.";
};
$test->callbackVar = $callbackVar;
$test->callbackVar->__invoke();
But as soon as I derive Test from Thread, running the script gives an error :
class Test extends Thread
{
public $callbackVar;
public function run() { }
}
$test = new Test();
$callbackVar = function()
{
echo "Callback var invoked.";
};
$test->callbackVar = $callbackVar;
// assert() returns true
assert($test->callbackVar === null);
$test->callbackVar->__invoke();
With the following output
Fatal error: Call to a member function __invoke() on a non-object
Anyone ever had this issue ? Any possible workaround ? I'd rather not use eval if possible... I've tried many workarounds, such as rewrapping into another closure, using a ReflectionFunction, ... nothing cuts it.
Zend does not allow you to serialize closure objects.
So it's not something you should try to work around, possibly at some time in the future Zend will allow serialization of Closures, pthreads will not require changes at that time.
You'll just have to do it the old fashioned way ...

Categories