From d8165c2502516dfda506e2f27aadec58041273ff Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Tue, 8 Jun 2021 14:31:55 +0200 Subject: [PATCH] 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. --- Zend/tests/bug81104.phpt | 23 +++++++++++++++++++++++ main/main.c | 14 ++++++++++++-- 2 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 Zend/tests/bug81104.phpt diff --git a/Zend/tests/bug81104.phpt b/Zend/tests/bug81104.phpt new file mode 100644 index 00000000000..fec7a7d25ef --- /dev/null +++ b/Zend/tests/bug81104.phpt @@ -0,0 +1,23 @@ +--TEST-- +Bug #81104: Warning: "Failed to set memory limit to ... bytes" emitted after exit in debug +--INI-- +memory_limit=5M +report_memleaks=0 +--FILE-- +x = [$this]; } +} +gc_disable(); +ini_set('memory_limit', '10M'); +$y = []; +for ($i = 0; $i < 10000; $i++) { + $y[] = new X(); +} +$y[0]->y = &$y; + +?> +===DONE=== +--EXPECT-- +===DONE=== diff --git a/main/main.c b/main/main.c index e675998575f..503d46d1904 100644 --- a/main/main.c +++ b/main/main.c @@ -303,8 +303,14 @@ static PHP_INI_MH(OnChangeMemoryLimit) value = Z_L(1)<<30; /* effectively, no limit */ } if (zend_set_memory_limit(value) == FAILURE) { - zend_error(E_WARNING, "Failed to set memory limit to %zd bytes (Current memory usage is %zd bytes)", value, zend_memory_usage(true)); - return FAILURE; + /* When the memory limit is reset to the original level during deactivation, we may be + * using more memory than the original limit while shutdown is still in progress. + * Ignore a failure for now, and set the memory limit when the memory manager has been + * shut down and the minimal amount of memory is used. */ + if (stage != ZEND_INI_STAGE_DEACTIVATE) { + zend_error(E_WARNING, "Failed to set memory limit to %zd bytes (Current memory usage is %zd bytes)", value, zend_memory_usage(true)); + return FAILURE; + } } PG(memory_limit) = value; return SUCCESS; @@ -1963,6 +1969,10 @@ void php_request_shutdown(void *dummy) shutdown_memory_manager(CG(unclean_shutdown) || !report_memleaks, 0); } zend_end_try(); + /* Reset memory limit, as the reset during INI_STAGE_DEACTIVATE may have failed. + * At this point, no memory beyond a single chunk should be in use. */ + zend_set_memory_limit(PG(memory_limit)); + /* 16. Deactivate Zend signals */ #ifdef ZEND_SIGNALS zend_signal_deactivate();