Skip to content

Commit d8165c2

Browse files
committed
Fixed bug #81104
When the memory limit is restored during shutdown, we may still be using a lot of memory. Ignore the failure at that point and set it again after the MM is shut down, at which point memory usage should be at its lowest point.
1 parent d818ede commit d8165c2

File tree

2 files changed

+35
-2
lines changed

2 files changed

+35
-2
lines changed

Zend/tests/bug81104.phpt

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
--TEST--
2+
Bug #81104: Warning: "Failed to set memory limit to ... bytes" emitted after exit in debug
3+
--INI--
4+
memory_limit=5M
5+
report_memleaks=0
6+
--FILE--
7+
<?php
8+
class X {
9+
public $x;
10+
public function __construct() { $this->x = [$this]; }
11+
}
12+
gc_disable();
13+
ini_set('memory_limit', '10M');
14+
$y = [];
15+
for ($i = 0; $i < 10000; $i++) {
16+
$y[] = new X();
17+
}
18+
$y[0]->y = &$y;
19+
20+
?>
21+
===DONE===
22+
--EXPECT--
23+
===DONE===

main/main.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -303,8 +303,14 @@ static PHP_INI_MH(OnChangeMemoryLimit)
303303
value = Z_L(1)<<30; /* effectively, no limit */
304304
}
305305
if (zend_set_memory_limit(value) == FAILURE) {
306-
zend_error(E_WARNING, "Failed to set memory limit to %zd bytes (Current memory usage is %zd bytes)", value, zend_memory_usage(true));
307-
return FAILURE;
306+
/* When the memory limit is reset to the original level during deactivation, we may be
307+
* using more memory than the original limit while shutdown is still in progress.
308+
* Ignore a failure for now, and set the memory limit when the memory manager has been
309+
* shut down and the minimal amount of memory is used. */
310+
if (stage != ZEND_INI_STAGE_DEACTIVATE) {
311+
zend_error(E_WARNING, "Failed to set memory limit to %zd bytes (Current memory usage is %zd bytes)", value, zend_memory_usage(true));
312+
return FAILURE;
313+
}
308314
}
309315
PG(memory_limit) = value;
310316
return SUCCESS;
@@ -1963,6 +1969,10 @@ void php_request_shutdown(void *dummy)
19631969
shutdown_memory_manager(CG(unclean_shutdown) || !report_memleaks, 0);
19641970
} zend_end_try();
19651971

1972+
/* Reset memory limit, as the reset during INI_STAGE_DEACTIVATE may have failed.
1973+
* At this point, no memory beyond a single chunk should be in use. */
1974+
zend_set_memory_limit(PG(memory_limit));
1975+
19661976
/* 16. Deactivate Zend signals */
19671977
#ifdef ZEND_SIGNALS
19681978
zend_signal_deactivate();

0 commit comments

Comments
 (0)