4

I'm writing a codeigniter application, upon doing a query i get hit with the following fatal error.

Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 262144 bytes) in /var/www/html/cryd/_zcore/core/Loader.php on line 262

I could increase the allowed memory size, but it seems that the issue could be much more graver, that if it is a memory leak, i'd just be giving php more memory to play around with. The query is not even that intensive, it just returns one row of data.

Here is my controller

    <?php
defined('BASEPATH') OR exit('No direct script access allowed');

class Invest_webhook extends CI_Controller {


    private $web_msg = null;
    private $proceed = 1;
    private $data = null;
    private $receive = null;
    private $complete = 0;
    private $member = null;
    private function loadPage($page,$data=null){
        $data = array_merge($data,$this->lang->language);
        $this->parser->parse('dashboard/header',$data);
        $this->parser->parse('dashboard/'.$page);
        $this->parser->parse('dashboard/footer');
    }

    public function webhook(){
        echo memory_get_peak_usage()."<br/>";
        //$update = file_get_contents("php://input");
        //$update = json_decode($update,true);

        $update = array(
            'notification_id' => '57233292b6a3d133e9c83822',
            'delivery_attempt' => 1,
            'type' => 'address',
            'data' => Array(
                'network' => "BTCTEST",
                'address' => '2N1jfZt8Uc721FAWNjdVpQZjfTxeG271RKy',
                'balance_change' => 1.00000000,
                'amount_sent' => 0.00000000,
                'amount_received' => 1.00000000,
                'txid' => '',
                'confirmations' => 4,
                'is_green' => false
            ),
            'created_at' => 1497176944
        );

        $data = $this->get_investment_data($update['data']['address']);
        if(!$data){
            die('This address does not exist');
        }

        $this->data = $data[0];
        $this->member = $this->get_member_data($this->data['tid']);

        //Start the process to verify transaction and credit investment
        $this->verify_investment();
        $this->update_investment();

        //$parameter = $this->web_msg;
        //include APPPATH."libraries/telegrambotv2.php";
        //$bot = new Telegram('331263599:AAEpHNAdyN1X5TenBk_QkJdt7xfwzDI6YeQ','bot');

        echo $this->web_msg."<br/>";        
    }

    private function verify_investment(){
        include APPPATH."/libraries/BlockIo.php";
        $this->load->config('block');
        $block = new BlockIo($this->config->item('api_token'),$this->config->item('api_secret'));
        $address = ($this->data['address']);
        $receive = $block->get_address_balance(array('addresses' => $address));

        $receive = $receive->data->available_balance;


        $expect = $this->data['inv'];

        settype($receive,'float');
        settype($expect,'float');
        echo '<br/>'.$receive."<br/>".$expect."<br/>";
        if($receive == $expect){

            $this->receive = $receive;
            return true;
        }
        $this->proceed = 0;
        $this->web_msg = 'inv_mismatch';
        return false;
    }

    private function get_member_data($tid){
        $this->load->model('invest_model','invest');
        return $this->get_member_data($tid);
    }

    private function update_investment(){
        if(!$this->proceed){
            return;
        }
        $this->load->model('invest_model','invest');

        $einv = $this->member['inv'];


        settype($einv,'float');

        $new_inv = $einv + $this->receive;
        $this->member['inv'] = $new_inv;
        $this->member['last_inv'] = 'NOW()';
        $this->data['confirmed'] = 1;

        if($this->invest->update_investment($this->data,$this->member)){
            $this->web_msg = 'inv_complete';
            $this->complete = 1;
            return true;
        } else {
            $this->proceed = 0;
            $this->web_msg = 'inv_unx_err';
            return false;
        }
    }

    private function get_investment_data($address){
        $this->load->model('invest_model','invest');
        return $this->invest->investment_data($address);
    }

    private function log($text){
        $file = fopen(APPPATH."/logs/investments/log.log",'a');
        fwrite($file,$text);
        fwrite($file,"\n");
        fclose($file);
    }
}

and here is my model

    <?php
defined('BASEPATH') OR exit('No direct script access allowed');

class Invest_model extends CI_Model {
    public function __construct(){
        parent::__construct();
    }

    public function investment_data($address){
        $this->db->where('address',$address);
        $this->db->where('confirmed',0);
        $f = $this->db->get('investments');
        return $f->result_array();
    }

    public function current_investment($tid){
        $this->db->select('inv');
        $this->db->where('tid',$tid);
        $f = $this->db->get('users');
        $f = $f->row_array();
        return $f;
    }

    public function get_member_data($tid){
        echo "<hr/>";
        echo memory_get_peak_usage()."<br/>";
        $this->db->where('tid',$tid);
        echo memory_get_peak_usage()."<br/>";
        $f = $this->db->get('users');
        echo memory_get_peak_usage()."<br/>";
        return $f->row_array();
    }

    public function update_investment($inv,$member){
        $this->db->trans_begin();
        $this->db->set($inv);
        $this->db->where('address',$inv['address']);
        $this->db->update('investments');
        $this->db->set($member);
        $this->db->where('tid',$member['tid']);
        $this->db->update('users');
        if($this->db->trans_status() === FALSE){
            $this->db->trans_rollback();
            return false;
        } else {
            $this->db->trans_commit();
            return true;
        }
    }

}

I am not as to where i can optimize this further, its pretty simple and straight forward, if its a problem in my logical appraoch, hopefully a better mind than mine will be able to spot and guide me further.

Thanks in advance.

5
  • I don't see any for or while loops which could be the cause. Also recursive calls could cause this. What is the DB layer you are using, e.g. $this->db->get Commented Jul 10, 2017 at 9:20
  • @Adder do you mean the driver i'm using? its mysqli. Commented Jul 10, 2017 at 9:24
  • I wasn't aware that mysqli alllows to do $this->db->where, I would have guessed this is from some homegrown DB layer. Commented Jul 10, 2017 at 9:35
  • one thing which is srsly odd - your directory structure /var/www/html/cryd/_zcore/core/Loader.php looks wrong, the Loader.php should be in [your_directory]system/core/ - what is your CI Version ? Commented Jul 10, 2017 at 10:30
  • @sintakonte the codeigniter installation has been configured to use separate application folder and separate core folder. All the core system is inside _zcore while all the application is inside _botadmin Commented Jul 10, 2017 at 11:17

5 Answers 5

3

Your code looks fine. Check if some function is getting called repeatedly.

You could use

ini_set('memory_limit', '-1');

as a temporary solution. or just increase the memory_limit

Chceck you php.ini file. If it is in the below form,

memory_limit=8G

Change that in the form of MB

memory_limit=8192M

You can also do it in your code like

ini_set('memory_limit', '8192M'); 
Sign up to request clarification or add additional context in comments.

Comments

2

Put this line on your codeigniter's index.php. So it will be affected for whole project.

ini_set('memory_limit', '-1');

Note: This is just a quick fix. This bug has not been resolved in php itself.

5 Comments

Well yeah this would work, but i'm just wondering if its something in my code. There are no recursive connections to the database or anything.
Do you mean, You have no idea what cause this problem?
Yes, i do not know what causes it. There are at most 3 calls to the database to retrieve information from 2-3 tables, then one query to update. None of which happen recursively. I must add flags to check this though
Check memory usage before and after each call.
A private method in the controller was calling itself over and over again until the allocated memory was exhausted.
1

The problem occurs because a private method kept calling itself over and over again until the allocated memory is exhausted and the script stops execution

private function get_member_data($tid){
    return $this->get_member_data($tid);
}

This is a stupid human error, the above method should have been re-written as below

private function get_member_data($tid){
//Call to model method
    return $this->invest->get_member_data($tid);
}

Sorry, and thanks everyone.

Comments

1

If anybody else has this problem:

Make sure your memory size in php.ini has an M after the number.

I had 512 in there....when I changed it to 512M .....no more problem.

z

Comments

0

If you want to know where the memory goes you should look into PHP memory profiling: PHP memory profiling

Personally I would just increase the PHP max_memory to 256MB and see if it's enough ;)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.