Run function in a separate process to avoid segfault - php

I have a big function, that I have to call a 50-100 times. Previously I used bash script like that:
#!/bin/bash
for i in {1..50}
do
RET=0
until [ ${RET} -eq 1 ]; do
php /scripts/cli.php $i
RET=$?
done
done
But i`m not good in bash scripting while I need to enchance logicwith returned values, so I tried to implement this in pure php with a function like that:
<?
require_once('cli.php');
for($cnt=1; $cnt<=50; $cnt++){
$cli = cli($cnt);
}
?>
But this approach results in segmentation fault after 10-15 cycles. Is it possible to run function in a separate process loke it was in bash script and clean resources to avoid memory leak?

Yes, you could look into proc_open if you need access to the child processes stdin/stdout/stderr or you could use the simpler functions: exec() or passthru().
That said.. PHP should not segfault, there must be some sort of buggy extension you're using. I'd focus more on fixing that than creating workarounds.

Related

Parallelism in php

I want to optimize part of my code to improve performance.Since my application make use of commandline tool , i think it would certainly improve performance to execute lines of code in parallel rather than executing code sequentially
<?php
$value = exec("command goes here"); //this takes time
/* Some instructions here that don't depend on $value */
/* Some instructions here that don't depend on $value */
$result = $value*2 ; //this is just a dumb example
?>
I want to execute the codes that don't depend on value at the same time as $value so that the whole script execute faster rather that waiting for exec() to complete
For a quick and dirty way of releasing your php thread from a blocking exec thread, you can simply append the command with a "&" or "& disown". In the example below I also redirected all errors and stdout to /dev/null. (I assume a linux system and just used a simple command that might take some amount of time...)
$command = "mv oldFolder/hugeFile.txt newFolder/hugeFile.txt >> /dev/null 2>&1 &";
$value=exec($command);
If you really need the return value from $command just remove the >> /dev/null 2>&1 bit.
Unfortunately PHP always despond you in parallelism, concurrent programming, ....
And I never know that why PHP doesn't support these important things and WHEN PHP WANT TO SUPPORT THESE.
But maybe you want to use Fork in php (if you know the problems AND Troubles in Fork )
http://php.net/manual/en/function.pcntl-fork.php
https://codereview.stackexchange.com/questions/22919/how-to-fork-with-php-4-different-approaches

I want to execute more than one method at a time in php

Hi Please help me in executing more than one method at a time in PHP.
Below is example:
<?php
function writeName()
{
sleep(3);
echo "Kai Jim Refsnes";
}
function b(){
sleep(3);
echo"b";
}
b();
writeName());
?>
Here above program take 6 sec to execute.But I want to run my both method simultaneously so that program should execute with in 3 sec(Multi threading).
With common PHP its not possible, because PHP is executed sequential. You may have a look at a job-server like gearman, or you may try to use forks (pcntl_fork()). It's not multi-threading, because there is no shared memory.
Sorry, but multithreading is not supported in PHP.
But you could start a PHP script which can run in the background using exec(). Just make sure you redirect it's output elsewhere.
That should be the closest you can get to "multithreading" without additional tools. Here's what the manual says:
Note: If a program is started with this function, in order for it to continue running in the background, the output of the program must be redirected to a file or another output stream. Failing to do so will cause PHP to hang until the execution of the program ends.

Executing functions parallelly in PHP

Can PHP call a function and don't wait for it to return? So something like this:
function callback($pause, $arg) {
sleep($pause);
echo $arg, "\n";
}
header('Content-Type: text/plain');
fast_call_user_func_array('callback', array(3, 'three'));
fast_call_user_func_array('callback', array(2, 'two'));
fast_call_user_func_array('callback', array(1, 'one'));
would output
one (after 1 second)
two (after 2 seconds)
three (after 3 seconds)
rather than
three (after 3 seconds)
two (after 3 + 2 = 5 seconds)
one (after 3 + 2 + 1 = 6 seconds)
Main script is intended to be run as a permanent process (TCP server). callback() function would receive data from client, execute external PHP script and then do something based on other arguments that are passed to callback(). The problem is that main script must not wait for external PHP script to finish. Result of external script is important, so exec('php -f file.php &') is not an option.
Edit:
Many have recommended to take a look at PCNTL, so it seems that such functionality can be achieved. PCNTL is not available in Windows, and I don't have an access to a Linux machine right now, so I can't test it, but if so many people have advised it, then it should do the trick :)
Thanks, everyone!
On Unix platforms you can enable the PCNTL functions, and use pcntl_fork to fork the process and run your jobs in child processes.
Something like:
function fast_call_user_func_array($func, $args) {
if (pcntl_fork() == 0) {
call_user_func_array($func, $args);
}
}
Once you call pcntl_fork, two processes will execute your code from the same position. The parent process will get a PID returned from pcntl_fork, while the child process will get 0. (If there's an error the parent process will return -1, which is worth checking for in production code).
You can check out PHP Process Control:
http://us.php.net/manual/en/intro.pcntl.php
Note: This is not threading, but the handling of separate processes. There is more overhead attached.
Wouldn't it solve your problem to fork, keeping the parent process free for other connections & actions? See http://www.php.net/pcntl_fork. If you need an answer back you could possibly listen to a socket in the parent, and write with the child. A simple while(true) loop with a read could possibly do, and probably you already have that basic functionality if you run a permanent TCP server. Another option would be to keep track of your childprocess-ids, keep a accessable store somewhere (file/database/memcached etc), with a pcnt_wait in the main process with a WNOHANG to check which process has exited, and retrieve the data from the store.
You can do some threading in PHP if you use the method pcntl_fork.
http://ca.php.net/manual/en/function.pcntl-fork.php
I have never use this myself, but the are some good example of how to use it on php.net.
PHP doesn't have this functionality as far as I know
You can emulate the function using a different technique, like this one:
Parallel functions in PHP
PHP does not support multi-threading, so there's no other option than taking advantage of the OS or the web server multi processing capabilities. Note that actually you can fetch both the result and output of exec:
string exec ( string $command [,
array &$output [, int &$return_var
]] )
You can, at least, prevent the parent process from hanging until the child process is done by ignoring the child signals using pcntl_signal(SIGCHLD, SIG_IGN).
So, let's say you want to fork a process and execute another PHP function that takes a while without making the parent wait for it to finish (since you want the main process to finish in a timely manner):
pcntl_signal(SIGCHLD, SIG_IGN);
$pid = pcntl_fork();
if ($pid < 0) {
exit(0);
} elseif (!$pid) {
my_slow_function();
exit(0);
}
// Parent keeps executing and finishes before the child does
If you want to execute a slow external script as the child process, pcntl_exec is handy:
$script = array('/path/to/my/script'); // E.g. /home/my_user/my_script.php
pcntl_exec('/path/to/program/executable',$script); // E.g. /usr/bin/php

Error handling for popen

I am using popen in PHP to execute a TCL file .
$cmd='C:/wamp/www/Tcl/bin/tclsh84.exe'; //windows
$ph = popen($cmd,'w')
But if someone restarts the machine or the tclsh84.exe process is killed . How do I know this error condition has occured ?
$ph is not returning 0 in these conditions.
Regards,
Mithun
you see the documentation of the tasklist utility from there. This utility is a kind of task manager in command line (a bit less feature since you can only list process and not affect them). Having that utility accessible on your server, you can use exec function to get list of process and work with that.
a probable code would be something like that:
function isTCLRunning(){
$running = false;
exec('tasklist.exe /fo CSV /fi tclsh84.exe', $output);
return count($output) == 1
}
note: this is completly untested you might want to play a bit with tasklist and make sure it is returning expected output before starting to code your PHP function.

php exec() error

I'm having a little problem with the following:
When I execute this line:
echo exec(createDir($somevariable));
I get this error:
Warning: exec() [function.exec]: Cannot execute a blank command in /home/mydir/myfile.inc.php on line 32
Any ideas.
Thanks.
exec() expects a string argument, which it would pass on to your operating system to be executed. In other words, this is a portal to the server's command line.
I'm not sure what function createDir() is, but unless it's returning a valid command line string, it's probably failing because of that.
In Linux, you might want to do something like
exec('/usr/bin/mkdir '.$path);
...on the other hand, you should abstain from using exec() at all costs. What you can do here, instead, is take a look at mkdir()
With exec you can execute system calls like if you were using the command line. It hasn't to do anything with executing PHP functions.
To create a directory you could do the following:
exec( 'mkdir [NAME OF DIRECTORY]' );
I'd guess that your createDir() function doesn't return anything. Might also be worth checking that $somevariable is also set to something sensible
You're misunderstanding the purpose of exec(). If all you want to do is create a directory then you should use mkdir().
I think I've derived from other posts and comments what it is you actually want to do:
I think createDir() is a PHP function you've written yourself. It does more than just make a directory - it populates it, and that might take some time.
For some reason you believe that the next command gets run before createDir() has finished working, and you thought that by invoking createDir() using exec() you could avoid this.
Tell me in a comment if this is way out, and I'll delete this answer.
It's seems unlikely that createDir() really does keep working after it's returned (if it does, then we call that 'asynchronous'). It would require the programmer to go out of their way to make it asynchronous. So check that assumption.
Even so, exec() is not for invoking PHP functions. It is for invoking shell commands (the kind of thing you type in at a command prompt). As many of us have observed, it is to be avoided unless you're very careful - the risk being that you allow a user to execute arbitrary shell commands.
If you really do have to wait for an asynchronous function to complete, there are a couple of ways this can be done.
The first way requires that the asynchronous function has been written in an amenable manner. Some APIs let you start an asynchronous job, which will give you a 'handle', then do some other stuff, then get the return status from the handle. Something like:
handle = doThreadedJob(myParam);
# do other stuff
results = getResults(handle);
getResults would wait until the job finished.
The second way isn't as good, and can be used when the API is less helpful. Unfortunately, it's a matter of finding some clue that the job is finished, and polling until it is.
while( checkJobIsDone() == false ) {
sleep(some time interval);
}
I'm guessing createDir() doesn't have a return value.
Try exec("mkdir $somevariable");

Categories