Calling a Python script from PHP using Multi-threading - php

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()

Related

How to call a function without wait it finishes in php?

I use Laravel framework in my project.
I need call a function in PHP but I don't need wait for this.
For example:
public function payment($Authority)
{
if (test == 1)
$this -> one($Authority); // don't wait for this call.
return view ("site.payment");
}
private function one($Authority)
{
// php code
// python code
}
Laravel has a queue job system. You could create a job to call that code and have your payment method dispatch the job to the queue for processing. (assuming you don't use the sync driver).
"Queues allow you to defer the processing of a time consuming task, such as sending an email, until a later time. Deferring these time consuming tasks drastically speeds up web requests to your application." - Laravel 5.3 Docs - Queues
public function payment($Authority)
{
if (test == 1) {
// send to queue for processing later
dispatch(new SomeJob($Authority));
}
return view ("site.payment");
}
You can try to use PThreads extension (http://php.net/pthreads):
<?php
// create your own class from Thread
class MyWorkerThreads extends Thread
{
private $workerId;
private $authority;
public function __construct($id, $authority)
{
$this->workerId = $id;
$this->authority = $authority;
}
// main function
public function run()
{
echo "Worker #{$this->workerId} ran" . PHP_EOL;
echo $authority;
// make some long run tasks
$html = file_get_contents('http://google.com?q=testing');
}
}
...
$worker = new WorkerThreads($i, $Authority);
// start new thread with long run task
$worker->start();
...
// You can wait for the job to be finished at any time, using join
$worker->join();
you can call another process to run the code with proc_open. You also can write it into a artisan command, then call the command run in another process.
Here is a example for use proc_open()

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];
}
}

Background Processing using pthread in php

I am trying to implement muti-threading in php using pthread to send emails. The basic idea here is to send email as a background job so that users dose not have to wait for the task to finish.
I have a service that users PHPMailer to send emails and its working fine. I am using the following code to muti thread
class ThreadWorkerService extends \Thread {
private $_runMethod;
private $_vars;
private $_autoloderPath;
function __construct($vars) {
$this->_vars = $vars;
$reflector = new \ReflectionClass('Composer\Autoload\ClassLoader');
$dir = dirname($reflector->getFileName());
$this->_autoloderPath = $dir . "/../autoload.php";
}
public function setRunMethod($method) {
$this->_runMethod = $method;
}
public function run() {
if (!class_exists('Composer\Autoload\ClassLoader')) {
if (file_exists($this->_autoloderPath )) {
require_once( $this->_autoloderPath );
} else {
echo "autoloder not found";
}
}
$method = $this->_runMethod;
$results = $method($this->_vars);
}
}
$storage = new \Threaded();
$storage['emails'] = $emailArray;
$storage['config'] = $config;
$threadWorker = new ThreadWorkerService($storage);
$threadWorker->setRunMethod(function ($vars) {
$emailArray = $vars['emails'];
$config = $vars['config'];
$emailService = new \MyServices\EmailService($config);
$emailService->sendAllEmails(true, $emailArray);
}
});
$threadWorker->start(PTHREADS_INHERIT_CONSTANTS);
The issue here is that the tread dose not execute if i don't use
$threadWorker->join();
which eliminates the whole purpose of muti-treading in this scenario, what I want to know is, if it is possible to keep the child thread alive even when the parent process is complete. I have even tried detaching the thread with no luck.
I am familiar with on how to do it with messaging services like RabbitMQ, but I want to keep the application independent.
The issue here is that the thread does not execute if I don't use: $threadWorker->join();, which eliminates the whole purpose of multi-threading in this scenario.
It is likely the case that the main thread's stdout, or some other dependency, is being closed or destroyed before the thread gets to execute.
Taken from the PHP manual for Thread:
Warning: Relying on the engine to determine when a Thread should join may cause undesirable behaviour; the programmer should be explicit, where possible.
You don't need to join immediately, but it is advisable to join explicitly.
The following example code illustrates the problem:
<?php
class Test extends Thread {
public function run() {
sleep(1);
echo "Thread\n";
}
}
$test = new Test();
$test->start();
echo "End\n";
?>
CPU speed permitting, the main context will begin to destroy the Thread before the Thread gets to echo.
You will normally get the output:
End
Thread
However, if the code is more complex, for example, code that manipulates dependencies set in the constructor of the Thread, those dependencies might have already been destroyed by the time they are used.
A last ditch attempt to join implicitly is made (in the most recent versions of pthreads), but you cannot rely on destruction order being compatible with your expectations, and so explicit join is preferable.
Noteworthy: The most recent versions of pthreads (PHP7+) prohibit execution anywhere but CLI; If this is code that is being executed at the frontend of a web server, you will need to rethink your architecture.

PHP pThreads IIS: unexpected output in browser

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()

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.

Categories