php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #65987 memory leak and handle leak in shmop
Submitted: 2013-10-29 00:42 UTC Modified: 2020-05-13 13:48 UTC
Votes:2
Avg. Score:4.0 ± 1.0
Reproduced:1 of 1 (100.0%)
Same Version:0 (0.0%)
Same OS:0 (0.0%)
From: sakamoto dot ta at saxa dot co dot jp Assigned:
Status: Analyzed Package: *Extensibility Functions
PHP Version: Irrelevant OS: Windows
Private report: No CVE-ID: None
View Add Comment Developer Edit
Anyone can comment on a bug. Have a simpler test case? Does it work for you on a different platform? Let us know!
Just going to say 'Me too!'? Don't clutter the database with that please — but make sure to vote on the bug!
Your email address:
MUST BE VALID
Solve the problem:
19 + 19 = ?
Subscribe to this entry?

 
 [2013-10-29 00:42 UTC] sakamoto dot ta at saxa dot co dot jp
Description:
------------
OS:Windows 2008 Server R2
PHP:Version 5.3.9

I received an answer and add shmop_delete the case () in Bug # 65949, but it does not improve.
Application error occurs when continue to operate the following script.

When I call the () shm_close the () shm_open, handle name
 \BaseNamedObjects\TSRM_SHM_DESCRIPTOR:x and 
 \BaseNamedObjects\TSRM_SHM_SEGMENT:x 
remains without being released. 
The amount of memory used will continue to increase.

This problem does not occur on Linux.


Test script:
---------------
<?php
    $shm_id = 0;
    $hex_shm_id = 0xff3;
    $write_d1 = "test #1 of the shmop() extension";
    $write_d2 = "test #2 append data to shared memory segment";
    for( ; ; )
    {
        echo "shm open for create : ";
        $shm_id = shmop_open($hex_shm_id, "c", 0644, 1024);
        if (!$shm_id) {
            die("failed\n");
        } else {
            echo "ok[".$shm_id."]\n";
        }

        echo "shm size is: " . ($shm_size = shmop_size($shm_id)) . "\n";
        echo "shm write test #1: ";

        $written = shmop_write($shm_id, $write_d1, 0);
        if ($written != strlen($write_d1)) {
            echo "failed\n";
        } else {
            echo "ok\n";
        }
        echo "data in memory is: " . shmop_read($shm_id, 0, $written) . "\n";
        // Add Next 2 Lines
        $delete_result = shmop_delete($shm_id);
        echo "shmop_delete return value [".$delete_result."]\n";
        shmop_close($shm_id);
        $shm_id = 0;

        sleep(1);
    }
?>


Expected result:
----------------
Memory leak and handle leak does not occur.


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2016-10-07 13:06 UTC] cmb@php.net
-Package: Unknown/Other Function +Package: *Extensibility Functions
 [2018-09-18 17:05 UTC] cmb@php.net
-Status: Open +Status: Verified -Operating System: Windows 2008 Server R2 +Operating System: Windows
 [2018-09-18 17:05 UTC] cmb@php.net
I can confirm that shmop_delete() still does not work on Windows
with current master.

The culprit appears to be the refcount (.shm_nattac) check[1]; it
seems to me this can't possibly work, since shmop_open() calls
shmat() which increases the refcount, so it is always greater than
1.

[1] <https://github.com/php/php-src/blob/php-7.3.0RC1/TSRM/tsrm_win32.c#L757>
 [2020-05-13 13:48 UTC] cmb@php.net
-Status: Verified +Status: Analyzed
 [2020-05-13 13:48 UTC] cmb@php.net
Well, the actual reason for this behavior is that our Windows
implementation of the shm*() functions is rather different from
the POSIX semantics, where shared memory is persistent, i.e. it is
retained even if all handles have been closed.  That is not the
case on Windows; if the last handle is closed, the shared memory
is freed.  So shmop_delete() is actually supposed to be a NOP
there.

However, shmop_close() does not close all handles to the shared
memory on Windows, because re-opening from the same process would
no longer be possible.  This cannot be changed in a revision
release due to BC concerns.

It may be reasonable to more closely match POSIX semantics in PHP
8.  This would require to create file mappings to actual files on
disk, instead of page-file backed memory.  As the shared memory
would then be persistent, shmop_close() could actually close all
handles, and shmop_delete() could be implemented in a way that
would delete the backing file on disk after all handles had been
closed.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Apr 18 11:01:28 2024 UTC