Skip to content

Commit

Permalink
Merge pull request #28 from drefixs/fix-memory-leak-bug
Browse files Browse the repository at this point in the history
Fix memory leak bug
  • Loading branch information
BitOne authored Nov 7, 2016
2 parents d2f837f + 2364479 commit 50ef567
Show file tree
Hide file tree
Showing 4 changed files with 217 additions and 10 deletions.
33 changes: 23 additions & 10 deletions extension/meminfo.c
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,7 @@ int meminfo_visit_item(const char * item_label, HashTable *visited_items)
void meminfo_hash_dump(php_stream *stream, HashTable *ht, zend_bool is_object, HashTable *visited_items, int *first_element)
{
zval **zval;
char *key;
char *key, *char_buf;;

HashPosition pos;
ulong num_key;
Expand All @@ -406,10 +406,13 @@ void meminfo_hash_dump(php_stream *stream, HashTable *ht, zend_bool is_object, H
if (is_object) {
const char *property_name, *class_name;
int mangled = zend_unmangle_property_name(key, key_len - 1, &class_name, &property_name);

php_stream_printf(stream TSRMLS_CC, " \"%s\":\"%p\"", meminfo_escape_for_json(property_name), *zval );
char_buf = meminfo_escape_for_json(property_name);
php_stream_printf(stream TSRMLS_CC, " \"%s\":\"%p\"", char_buf, *zval );
efree(char_buf);
} else {
php_stream_printf(stream TSRMLS_CC, " \"%s\":\"%p\"", meminfo_escape_for_json(key), *zval );
char_buf = meminfo_escape_for_json(key);
php_stream_printf(stream TSRMLS_CC, " \"%s\":\"%p\"", char_buf, *zval );
efree(char_buf);
}

break;
Expand All @@ -432,6 +435,7 @@ void meminfo_hash_dump(php_stream *stream, HashTable *ht, zend_bool is_object, H
void meminfo_zval_dump(php_stream * stream, char * frame_label, char * symbol_name, zval * zv, HashTable *visited_items, int *first_element)
{
char zval_id[16];
char *char_buf;
sprintf(zval_id, "%p", zv);

if (meminfo_visit_item(zval_id, visited_items)) {
Expand All @@ -450,10 +454,14 @@ void meminfo_zval_dump(php_stream * stream, char * frame_label, char * symbol_na

if (frame_label) {
if (symbol_name) {
php_stream_printf(stream TSRMLS_CC, " \"symbol_name\" : \"%s\",\n", meminfo_escape_for_json(symbol_name));
char_buf = meminfo_escape_for_json(symbol_name);
php_stream_printf(stream TSRMLS_CC, " \"symbol_name\" : \"%s\",\n", char_buf);
efree(char_buf);
}
php_stream_printf(stream TSRMLS_CC, " \"is_root\" : true,\n");
php_stream_printf(stream TSRMLS_CC, " \"frame\" : \"%s\"\n", meminfo_escape_for_json(frame_label));
char_buf = meminfo_escape_for_json(frame_label);
php_stream_printf(stream TSRMLS_CC, " \"frame\" : \"%s\"\n", char_buf);
efree(char_buf);
} else {
php_stream_printf(stream TSRMLS_CC, " \"is_root\" : false\n");
}
Expand All @@ -466,7 +474,9 @@ void meminfo_zval_dump(php_stream * stream, char * frame_label, char * symbol_na
int is_temp;

php_stream_printf(stream TSRMLS_CC, ",\n");
php_stream_printf(stream TSRMLS_CC, " \"class\" : \"%s\",\n", meminfo_escape_for_json(meminfo_get_classname(zv->value.obj.handle)));
char_buf = meminfo_escape_for_json(meminfo_get_classname(zv->value.obj.handle));
php_stream_printf(stream TSRMLS_CC, " \"class\" : \"%s\",\n", char_buf);
efree(char_buf);
php_stream_printf(stream TSRMLS_CC, " \"object_handle\" : \"%d\",\n", zv->value.obj.handle);

properties = Z_OBJDEBUG_P(zv, is_temp);
Expand All @@ -486,6 +496,7 @@ void meminfo_zval_dump(php_stream * stream, char * frame_label, char * symbol_na
php_stream_printf(stream TSRMLS_CC, "\n");
}
}

/**
* Get size of an element
*
Expand Down Expand Up @@ -522,11 +533,13 @@ zend_ulong meminfo_get_element_size(zval *zv)
char * meminfo_escape_for_json(const char *s)
{
int new_str_len;
char *s1;
char *s1, *s2;
s1 = php_str_to_str((char*)s, strlen(s), "\\", 1, "\\\\", 2, &new_str_len);
s2 = php_str_to_str(s1, strlen(s1), "\"", 1, "\\\"", 2, &new_str_len);

s1 = php_str_to_str(s, strlen(s), "\\", 1, "\\\\", 2, &new_str_len);
efree(s1);

return php_str_to_str(s1, strlen(s1), "\"", 1, "\\\"", 2, &new_str_len);
return s2;
}

/**
Expand Down
45 changes: 45 additions & 0 deletions extension/tests/fixture/book.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [
]>
<book id="listing">
<title>My lists</title>
<chapter id="books">
<title>My books</title>
<para>
<informaltable>
<tgroup cols="4">
<thead>
<row>
<entry>Title</entry>
<entry>Author</entry>
<entry>Language</entry>
<entry>ISBN</entry>
</row>
</thead>
<tbody>
<row>
<entry>The Grapes of Wrath</entry>
<entry>John Steinbeck</entry>
<entry>en</entry>
<entry>0140186409</entry>
</row>
<row>
<entry>The Pearl</entry>
<entry>John Steinbeck</entry>
<entry>en</entry>
<entry>014017737X</entry>
</row>
<row>
<entry>Samarcande</entry>
<entry>Amine Maalouf</entry>
<entry>fr</entry>
<entry>2253051209</entry>
</row>
<!-- TODO: I have a lot of remaining books to add.. -->
</tbody>
</tgroup>
</informaltable>
</para>
</chapter>
</book>
112 changes: 112 additions & 0 deletions extension/tests/info_dump.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
--TEST--
meminfo_objects_list with some objects
--FILE--
<?php
$docTest = new DOMDocument();
$docTest->load(__DIR__.'/fixture/book.xml');

$rFilePointer = fopen('php://memory', 'rw');

$arrayTest = [
'itemBool' => true,
'itemInteger' => 23,
'itemDoubles' => 1.2e3,
'itemNull' => null,
'itemString' => 'hello',
'itemObject' => $docTest,
'itemArray' => (array) $docTest,
'itemResource' => $rFilePointer,
];

meminfo_info_dump($rFilePointer);

rewind($rFilePointer);
$jsonO = json_decode(stream_get_contents($rFilePointer), true);
fclose($rFilePointer);
if (is_array($jsonO)) {
$items = $jsonO['items'];
printf(
"meminfo_info_dump JSON decode ok\nz_val_count:%d\n",
count($items)
);
uasort($items, function ($itemA, $itemB) {
return $itemA['type'] > $itemB['type']
|| ($itemA['type'] == $itemB['type'] && $itemA['size'] > $itemB['size']);
});

foreach($items as $item){
printf(
"item type:%s size:%d\n",
$item['type'],
$item['size']
);
}
} else {
echo 'meminfo_info_dump JSON decode fail';
}
?>
--EXPECT--
meminfo_info_dump JSON decode ok
z_val_count:62
item type:array size:96
item type:array size:96
item type:array size:96
item type:array size:96
item type:array size:96
item type:array size:96
item type:array size:96
item type:array size:96
item type:boolean size:24
item type:boolean size:24
item type:boolean size:24
item type:boolean size:24
item type:boolean size:24
item type:boolean size:24
item type:boolean size:24
item type:boolean size:24
item type:boolean size:24
item type:boolean size:24
item type:double size:24
item type:double size:24
item type:integer size:24
item type:integer size:24
item type:integer size:24
item type:integer size:24
item type:null size:24
item type:null size:24
item type:null size:24
item type:null size:24
item type:null size:24
item type:null size:24
item type:null size:24
item type:null size:24
item type:null size:24
item type:object size:56
item type:resource size:24
item type:string size:24
item type:string size:24
item type:string size:25
item type:string size:25
item type:string size:25
item type:string size:25
item type:string size:27
item type:string size:27
item type:string size:27
item type:string size:29
item type:string size:29
item type:string size:29
item type:string size:29
item type:string size:33
item type:string size:37
item type:string size:46
item type:string size:64
item type:string size:64
item type:string size:64
item type:string size:84
item type:string size:84
item type:string size:84
item type:string size:84
item type:string size:84
item type:string size:87
item type:string size:87
item type:string size:1054
37 changes: 37 additions & 0 deletions extension/tests/info_dump_memory-leak.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
--TEST--
meminfo_objects_list with some objects
--FILE--
<?php
$docTest = new DOMDocument();
$docTest->load(__DIR__.'/fixture/book.xml');

$rFilePointer = fopen('/dev/null', 'rw');

$arrayTest = [
'itemBool' => true,
'itemInteger' => 23,
'itemDoubles' => 1.2e3,
'itemNull' => null,
'itemString' => 'hello',
'itemObject' => $docTest,
'itemArray' => (array) $docTest,
'itemResource' => $rFilePointer,
];
$attemptCount = 1000;
gc_collect_cycles();
$startM = memory_get_usage(true);
while ($attemptCount-- > 0) {
meminfo_info_dump($rFilePointer);
}
fclose($rFilePointer);
gc_collect_cycles();
$endM = memory_get_usage(true);
if ($endM / $startM < 2) {
echo 'Memory leak test was successful';
} else {
echo "Memory leak test was failed\n";
printf("Memory leak:%s bytes",$endM - $startM);
}
?>
--EXPECT--
Memory leak test was successful

0 comments on commit 50ef567

Please sign in to comment.