Search code examples
phpcodeigniterforkubuntu-server

fork doesn't work although I checked it's installed and running on my server


I installed fork on my Ubuntu Server (using PHP-Apache-Codeigniter), and checked if it's working using var_dump (extension_loaded('pcntl')); and got a "true" output (How to check PCNTL module exists).

I have this code:

public function add_keyword() {

    $keyword_p = $this->input->post('key_word');

    $prod      = $this->input->post('prod_name');
    $prod      = $this->kas_model->search_prod_name($prod);
    $prod      = $prod[0]->prod_id;

    $country   = $this->input->post('key_country');

    $keyword = explode(", ", $keyword_p);
    var_dump($keyword); 
    $keyword_count = count($keyword);
    echo "the keyword count: $keyword_count";

    // Create   fork
    $pid = pcntl_fork();
    if(!$pid){

        for ($i=0; $i < $keyword_count ; $i++) { 

            // Inserts the inputs to the "keywords" table
            $this->kas_model->insert_keyword($keyword[$i], $prod, $country);

            // Gets relevant IDs for the inserted prod and keyword
            $last_inserted_key = $this->kas_model->get_last_rec('keywords');
            $keyword_id        = $last_inserted_key[0]->key_id;
            $prod_id           = $last_inserted_key[0]->key_prod;
            $prod_id_query     = $this->kas_model->get_prod_row_by_id($prod_id);
            $prod_id_a  = $prod_id_query[0]->prod_a_id;
            $prod_id_b  = $prod_id_query[0]->prod_b_id; 

            // Run the keyword query (on API) for today on each one of the keys and insert to DB aslong that the ID isn't 0.  
            if ( ($prod_id_a != 0) || ( !empty($prod_id_a) ) ) {
                $a_tdr = $this->get_var1_a_by_id_and_kw( $prod_id_a, $keyword[$i], $country);
            } else {
                $a_tdr['var1'] = 0;
                $a_tdr['var2'] = 0;
                $a_tdr['var3'] = 0;
            }

            if ( ($prod_id_b != 0) || ( !empty($prod_id_b) ) ) {
                $b_tdr = $this->get_var1_b_by_id_and_kw($prod_id_b, $keyword[$i], $country);
            } else {
                $b_tdr['var1'] = 0;
                $b_tdr['var2'] = 0;
                $b_tdr['var3'] = 0;     
            }

            $this->kas_model->insert_new_key_to_db($keyword_id, $a_tdr['var1'], $b_tdr['var1'], $a_tdr['var2'], $b_tdr['var2'], $a_tdr['var3'], $b_tdr['var3']);

        }
        exit($i);
    }


    // we are the parent (main), check child's (optional)
    while(pcntl_waitpid(0, $status) != -1){
        $status = pcntl_wexitstatus($status);
         // echo "Child $status completed\n";
        redirect('main/kas'); 
    }

    redirect('main/kas'); 
}

What the function does?

This function gets 1 or more keyword/s, a country var, and a product ID, and runs a query on an external slow API getting variables (runs other functions from within that same controller), and adds them to the database.

Problem: When running this function, and if I insert a lot of keywords, the page loads, and loads, and loads, for a long time, until it's done, and only then - I can continue browsing my website. So I was told to fork it since it's just sending a request to process it in the background, so whenever clicking the submit button, I get redirected to "main/kas".

Currently: I don't get redirected but the function runs without any errors.

I was told that it suppose to work but it's not - so I'm guessing I am doing something wrong within the code (?), or something else isn't working from within the server (???). This is my first time working with fork so I don't know a lot of how to operate with in (in syntax or from within the server).

Can you please help me debug the problem?


Solution

  • http://www.electrictoolbox.com/mysql-connection-php-fork/

    Reason for the error The parent and child processes all share the same database connection. When the first child process exits it will disconnect from the database, which means the same connection all processes are using will be disconnected, causing any further queries to fail.

    The solution The solution is to disconnect from the database before forking the sub processes and then establish a new connection in each process. The fourth parameter also should be passed to the mysql_connect function as "true" to ensure a new link is established; the default is to share an existing connection is the login details are the same.

    The question is!

    Is that efficient to connect to the server in the child and if there are any other alternative ways to do this better.