Sfoglia il codice sorgente

! Updates to better manage memory requests

Spuds 13 anni fa
parent
commit
9bc133e941

+ 2 - 2
Sources/Admin.php

@@ -613,7 +613,7 @@ function DisplayAdminFile()
 {
 	global $context, $modSettings, $smcFunc;
 
-	@ini_set('memory_limit', '32M');
+	setMemoryLimit('32M');
 
 	if (empty($_REQUEST['filename']) || !is_string($_REQUEST['filename']))
 		fatal_lang_error('no_access', false);
@@ -702,7 +702,7 @@ function AdminSearchInternal()
 	global $context, $txt, $helptxt, $scripturl, $sourcedir;
 
 	// Try to get some more memory.
-	@ini_set('memory_limit', '128M');
+	setMemoryLimit('128M');
 
 	// Load a lot of language files.
 	$language_files = array(

+ 1 - 1
Sources/Class-Package.php

@@ -38,7 +38,7 @@ class xmlArray
 	public function __construct($data, $auto_trim = false, $level = null, $is_clone = false)
 	{
 		// If we're using this try to get some more memory.
-		@ini_set('memory_limit', '32M');
+		setMemoryLimit('32M');
 
 		// Set the debug level.
 		$this->debug_level = $level !== null ? $level : error_reporting();

+ 3 - 3
Sources/DumpDatabase.php

@@ -44,12 +44,12 @@ function DumpDatabase2()
 
 	// Attempt to stop from dying...
 	@set_time_limit(600);
-	if (ini_get('memory_limit') < 256)
-		@ini_set('memory_limit', '256M');
+	
+	// @todo ... fail on not getting the requested memory?
+	setMemoryLimit('256M');
 
 	// Start saving the output... (don't do it otherwise for memory reasons.)
 	if (isset($_REQUEST['compress']) && function_exists('gzencode'))
-	
 	{
 		// Make sure we're gzipping output, but then say we're not in the header ^_^.
 		if (empty($modSettings['enableCompressedOutput']))

+ 1 - 1
Sources/Load.php

@@ -1293,7 +1293,7 @@ function detectBrowser()
 		);
 
 		// Detect IE7 and not IE8/IE9 in combat mode.
-		$context['browser']['is_ie7'] = strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE 7') !== false && (!$context['browser']['is_ie8'] || !$context['browser']['is_ie9']);
+		$context['browser']['is_ie7'] = strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE 7') !== false && !($context['browser']['is_ie8'] || $context['browser']['is_ie9']);
 
 		// Before IE8 we need to fix IE... lots!
 		$context['browser']['ie_standards_fix'] = ($context['browser']['is_ie8'] || $context['browser']['is_ie9']) ? false : true;

+ 1 - 1
Sources/Packages.php

@@ -1559,7 +1559,7 @@ function PackagePermissions()
 	}
 
 	// This is a memory eat.
-	@ini_set('memory_limit', '128M');
+	setMemoryLimit('128M');
 	@set_time_limit(600);
 
 	// Load up some FTP stuff.

+ 1 - 1
Sources/RepairBoards.php

@@ -31,7 +31,7 @@ function RepairBoards()
 	isAllowedTo('admin_forum');
 
 	// Try secure more memory.
-	@ini_set('memory_limit', '128M');
+	setMemoryLimit('128M');
 
 	// Print out the top of the webpage.
 	$context['page_title'] = $txt['admin_repair'];

+ 1 - 1
Sources/Reports.php

@@ -237,7 +237,7 @@ function BoardPermissionsReport()
 	global $context, $txt, $modSettings, $smcFunc;
 
 	// Get as much memory as possible as this can be big.
-	@ini_set('memory_limit', '256M');
+	setMemoryLimit('256M');
 
 	if (isset($_REQUEST['boards']))
 	{

+ 30 - 1
Sources/Subs-Graphics.php

@@ -65,6 +65,7 @@ function downloadAvatar($url, $memID, $max_width, $max_height)
 		array('id_attach')
 	);
 	$attachID = $smcFunc['db_insert_id']('{db_prefix}attachments', 'id_attach');
+	
 	// Retain this globally in case the script wants it.
 	$modSettings['new_avatar_data'] = array(
 		'id' => $attachID,
@@ -269,6 +270,31 @@ function checkGD()
 	return true;
 }
 
+/**
+ * See if we have enough memory to thumbnail an image
+ *
+ * @return whether we do
+ */
+function imageMemoryCheck($sizes)
+{
+	global $modSettings;
+	
+	// doing the old 'set it and hope' way?
+	if (empty($modSettings['attachment_thumb_memory']))
+	{
+		setMemoryLimit('90M');
+		return true;
+	}
+
+	// Determine the memory requirements for this image, note: if you want to use an image formula W x H x bits/8 x channels x Overhead factor
+	// you will need to account for single bit images as GD expands them to an 8 bit and will greatly overun the calculated value.  The 5 is 
+	// simply a shortcut of 8bpp, 3 channels, 1.66 overhead
+	$needed_memory = ($sizes[0] * $sizes[1] * 5);
+	
+	// if we need more, lets try to get it
+	return setMemoryLimit($needed_memory, true);
+}
+
 /**
  * Resizes an image from a remote location or a local file.
  * Puts the resized image at the destination location.
@@ -299,7 +325,6 @@ function resizeImageFile($source, $destination, $max_width, $max_height, $prefer
 	);
 
 	require_once($sourcedir . '/Subs-Package.php');
-	@ini_set('memory_limit', '90M');
 
 	$success = false;
 
@@ -332,6 +357,10 @@ function resizeImageFile($source, $destination, $max_width, $max_height, $prefer
 	// We can't get to the file.
 	else
 		$sizes = array(-1, -1, -1);
+		
+	// See if we have -or- can get the need memory for this operation
+	if (!imageMemoryCheck($sizes))
+		return false;
 
 	// A known and supported format?
 	// @todo test PSD and gif.

+ 2 - 2
Sources/Subs-Members.php

@@ -39,9 +39,9 @@ function deleteMembers($users, $check_not_admin = false)
 
 	// Try give us a while to sort this out...
 	@set_time_limit(600);
+	
 	// Try to get some more memory.
-	if (ini_get('memory_limit') < 128)
-		@ini_set('memory_limit', '128M');
+	setMemoryLimit('128M');
 
 	// If it's not an array, make it so!
 	if (!is_array($users))

+ 7 - 2
Sources/Subs-Package.php

@@ -2426,8 +2426,11 @@ function package_get_contents($filename)
 
 	if (!isset($package_cache))
 	{
+	
+		$mem_check = setMemoryLimit('128M');
+
 		// Windows doesn't seem to care about the memory_limit.
-		if (!empty($modSettings['package_disable_cache']) || ini_set('memory_limit', '128M') !== false || stripos(PHP_OS, 'win') !== false)
+		if (!empty($modSettings['package_disable_cache']) || $mem_check || stripos(PHP_OS, 'win') !== false)
 			$package_cache = array();
 		else
 			$package_cache = false;
@@ -2456,7 +2459,9 @@ function package_put_contents($filename, $data, $testing = false)
 	if (!isset($package_cache))
 	{
 		// Try to increase the memory limit - we don't want to run out of ram!
-		if (!empty($modSettings['package_disable_cache']) || ini_set('memory_limit', '128M') !== false || stripos(PHP_OS, 'win') !== false)
+		$mem_check = setMemoryLimit('128M');
+		
+		if (!empty($modSettings['package_disable_cache']) || $mem_check || stripos(PHP_OS, 'win') !== false)
 			$package_cache = array();
 		else
 			$package_cache = false;

+ 62 - 0
Sources/Subs.php

@@ -2965,6 +2965,68 @@ function setupThemeContext($forceload = false)
 	$context['meta_keywords'] = !empty($modSettings['meta_keywords']) ? $smcFunc['htmlspecialchars']($modSettings['meta_keywords']) : '';
 }
 
+/**
+ * Helper function to set the system memory to a needed value
+ * - If the needed memory is greater than current, will attempt to get more
+ * - if in_use is set to true, will also try to take the current memory usage in to account
+ *
+ * @param string $needed The amount of memory to request, if needed, like 256M
+ * @param bool $in_use Set to true to account for current memory usage of the script
+ * @return bool, true if we have at least the needed memory
+ */
+function setMemoryLimit($needed, $in_use = false) 
+{
+	// everything in bytes
+	$memory_used = 0;
+	$memory_current = memoryReturnBytes(ini_get('memory_limit'));
+	$memory_needed = memoryReturnBytes($needed);
+	
+	// should we account for how much is currently being used?
+	if ($in_use)
+		$memory_needed += function_exists('memory_get_usage') ? memory_get_usage() : (2 * 1048576);
+
+	// if more is needed, request it
+	if ($memory_current < $memory_needed)
+	{
+		@ini_set('memory_limit', ceil($memory_needed / 1048576) . 'M');
+		$memory_current = memoryReturnBytes(ini_get('memory_limit'));
+	}
+
+	$memory_current = max($memory_current, memoryReturnBytes(get_cfg_var('memory_limit')));
+
+	// return success or not
+	return (bool) ($memory_current >= $memory_needed);
+}
+
+/**
+ * Helper function to convert memory string settings to bytes
+ *
+ * @param string $val The byte string, like 256M or 1G
+ * @return integer The string converted to a proper integer in bytes
+ */
+function memoryReturnBytes($val) 
+{
+	if (is_integer($val)) 
+		return $val;
+	
+	// Separate the number from the designator
+	$val = trim($val);
+	$num = intval(substr($val, 0, strlen($val) - 1));
+	$last = strtolower(substr($val, -1));
+	
+	// convert to bytes
+	switch ($last) 
+	{
+		case 'g':
+			$num *= 1024;
+		case 'm':
+			$num *= 1024;
+		case 'k':
+			$num *= 1024;
+	}
+	return $num;
+}
+
 /**
  * This is the only template included in the sources.
  */