php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #75945 php leak memory when calling database function with 'RAISE NOTICE'
Submitted: 2018-02-09 20:30 UTC Modified: 2021-01-15 14:32 UTC
From: hnguyen at wyebot dot com Assigned: cmb (profile)
Status: Not a bug Package: PostgreSQL related
PHP Version: 7.2.2 OS: Ubuntu
Private report: No CVE-ID: None
 [2018-02-09 20:30 UTC] hnguyen at wyebot dot com
Description:
------------
Whenever php make a call to a postgresql database function with the 'RAISE NOTICE' statement in it then it leaks memory.

With the provided memTest.php script, if one run it on php 7.1 or 7.2, there is a memory leak reported. Testing on php 7.0 leak memory but by comparison it is much less. Please see below result.

Here is a test result with php 7.2:

# php -v
PHP 7.2.2-1+ubuntu16.04.1+deb.sury.org+1 (cli) (built: Feb  1 2018 16:01:26) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies
    with Zend OPcache v7.2.2-1+ubuntu16.04.1+deb.sury.org+1, Copyright (c) 1999-2018, by Zend Technologies

# ./memTest.php
php-psql memory leak test for function with 'RAISE NOTICE'
After 1000 runs memory lost = 84920 bytes

Here is a test result with php 7.1:

# php -v
PHP 7.1.13-1+ubuntu16.04.1+deb.sury.org+1 (cli) (built: Jan  5 2018 13:26:45) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.1.0, Copyright (c) 1998-2017 Zend Technologies
    with Zend OPcache v7.1.13-1+ubuntu16.04.1+deb.sury.org+1, Copyright (c) 1999-2017, by Zend Technologies

# ./memTest.php 
php-psql memory leak test for function with 'RAISE NOTICE'
After 1000 runs memory lost = 84920 bytes

Here is a test result with php 7.0:

# php -v
PHP 7.0.22-0ubuntu0.16.04.1 (cli) ( NTS )
Copyright (c) 1997-2017 The PHP Group
Zend Engine v3.0.0, Copyright (c) 1998-2017 Zend Technologies
    with Zend OPcache v7.0.22-0ubuntu0.16.04.1, Copyright (c) 1999-2017, by Zend Technologies

# ./memTest.php 
php-psql memory leak test for function with 'RAISE NOTICE'
After 1000 runs memory lost =  112 bytes


Test script:
---------------
# memTest.php script
# usage: ./memTest.php

#!/usr/bin/env php
<?php

const NUM_RUNS = 1000;

function addNoticeFunction($con)
{
    $query = "CREATE OR REPLACE FUNCTION test_function () RETURNS void AS $$ BEGIN RAISE NOTICE 'Hellow World!'; END; $$ LANGUAGE plpgsql;"; // this function will cause memory leak
    //$query = "CREATE OR REPLACE FUNCTION test_function () RETURNS void AS $$ BEGIN END; $$ LANGUAGE plpgsql;"; // this function will not cause memory leak
    $rs_client = pg_query($con, $query) or die("Cannot execute query: $query\n");
    if ($rs_client)
      pg_free_result($rs_client);

}

function makeAQuery($con)
{
    $query = "SELECT test_function()"; // lose 424 byte each run
    $rs_client = pg_query($con, $query) or die("Cannot execute query: $query\n");
    if ($rs_client)
      pg_free_result($rs_client);
}

function runQueryTests ($con)
{
    $before = memory_get_usage();
    for ($i = 0; $i < NUM_RUNS; ++$i) {
        makeAQuery($con);
    }
    $after = memory_get_usage();
    printf("After %d runs memory lost = %4d bytes\n", NUM_RUNS, $after - $before);
}

print("php-psql memory leak test for function with 'RAISE NOTICE'\n");
$con = pg_pconnect("host=172.17.0.1 user=postgres") or go_die("Could not connect to server\n");
addNoticeFunction($con);
runQueryTests($con);
pg_close($con);


?>


Expected result:
----------------
There should be 0 memory leak

Actual result:
--------------
There was 84920 bytes of memory leak after running the script

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2018-04-23 08:31 UTC] yohgaki@php.net
I haven't look into the details, but notice has it's own data structure hidden from users. These memory is cleaned up at request shutdown.
Therefore, you cannot test leak by user space script.

If you have excessive memory usage, e.g. hit memory_limits by raising thousands of notices, then it may be called a bug. I don't remember it stores all notices until shutdown or it has limit.
 [2021-01-15 14:32 UTC] cmb@php.net
-Status: Open +Status: Not a bug -Assigned To: +Assigned To: cmb
 [2021-01-15 14:32 UTC] cmb@php.net
Indeed, this is not a bug, since all notices need to be retained
in case pg_last_notice(…, PGSQL_NOTICE_ALL) is called.  You can
manually clear the notices by calling pg_last_notice(…,
PGSQL_NOTICE_CLEAR).
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sat Dec 21 12:01:31 2024 UTC