Calling a function in a background thread / process (forking)

27,114

Solution 1

From "Tudor Barbu's professional blog"
(http://blog.motane.lu/2009/01/02/multithreading-in-php/)

require_once( 'Thread.php' );

// test to see if threading is available
if( ! Thread::isAvailable() ) {
    die( 'Threads not supported' );
}

// function to be ran on separate threads
function paralel( $_limit, $_name ) {
    for ( $index = 0; $index < $_limit; $index++ ) {
        echo 'Now running thread ' . $_name . PHP_EOL;
        sleep( 1 );
    }
}

// create 2 thread objects
$t1 = new Thread( 'paralel' );
$t2 = new Thread( 'paralel' );

// start them
$t1->start( 10, 't1' );
$t2->start( 10, 't2' );

// keep the program running until the threads finish
while( $t1->isAlive() && $t2->isAlive() ) {

}

Download Thread.php

Solution 2

If you are using Linux you can take advantage of the command line and do

public function newWrapperInstance($start,$end){
    exec('bash -c "exec nohup setsid php-cli yourFile.php '.$start.' '.$end.' > /dev/null 2>&1 &"');
}

This will create a new instance of PHP in the background and detach itself from the exec function in the primary thread.

Warning: The only downside is you can't control what those threads do once they are created.

Share:
27,114
Ayush
Author by

Ayush

I have a keen interest in the Language Development stack (Parsers, Lexers, ASTs, Compilers and VMs), Web development and Javascript frameworks (particularly AngularJS) along with security and cryptography. Lately been working on infrastructure and service monitoring, containers and Kubernetes.

Updated on June 17, 2020

Comments

  • Ayush
    Ayush almost 4 years

    I have code that's somewhat like this:

    ($i=0; $i < 100; $i++)
    {
       do ($foo[$i]);
    }
    

    The above is a time intensive task, and I was hoping to be able to create a function, and call it twice like below

    function wrapper($start;$end)
    {
        ($i=$start; $i < $end; $i++)
        {
           do ($foo[$i]);
        }
    }
    //have both of these run in parallel
    wrapper(0,50);
    wrapper(51,100);
    

    I looked at Gearman but I cannot use it as I cannot install the gearman server (since I'm on a shared server). It seems like the way to achieve this would be by forking. I tried reading up a lot about it, but documentation and support is scant. Any help / wireframe code would be appreciated.

    To define my question, how could I call wrapper() passing in arguments such that it executes in a child process. Also, its important that I be able to register a callback function.

    Additional Details: PHP 5.3, running on Linux server. Script is executed by cgi-fcgi.

    I think this is how I am supposed to spawn a child process, but how can I use it to spawn multiple child processes? And how do I register a callback function?

    $pid = pcntl_fork(); 
    
    if ( $pid == -1 ) {        
        // Fork failed            
        exit(1); 
    } else if ( $pid ) { 
        // The parent process
        //should I repeat this same code here to spawn another child process?
    
    } else { 
        // the child process 
        //can I call wrapper from here and will it run in this child process?
    
  • Ayush
    Ayush over 12 years
    Thanks. This seems like a brilliant wrapper. I'm looking into the code right now
  • Kelvin
    Kelvin over 12 years
    The link you reference also says it's bad to use an empty loop to check if threads are alive, because it will use up all your CPU. You should include a sleep in the loop.
  • Jason
    Jason about 8 years
    @Kelvin, a better solution is to implement a join capability to the library, should be fairly simple to do.
  • Sceptical Jule
    Sceptical Jule almost 6 years
    How can I start a class method using this approach?