From dc496c02d9aa0519f94bfd2c8ffa1ba013058863 Mon Sep 17 00:00:00 2001 From: Aaron Schulz Date: Tue, 14 Jan 2014 11:36:26 -0800 Subject: [PATCH] Limit attempts to render the same thumbnail after failures bug: 49118 Change-Id: I9379ec445bf2e77bd3b085c00182c5e406ed300d --- RELEASE-NOTES-1.23 | 3 +++ includes/DefaultSettings.php | 8 ++++++ languages/messages/MessagesEn.php | 1 + languages/messages/MessagesQqq.php | 4 ++- maintenance/language/messages.inc | 1 + thumb.php | 43 ++++++++++++++++++++++++++++++ 6 files changed, 59 insertions(+), 1 deletion(-) diff --git a/RELEASE-NOTES-1.23 b/RELEASE-NOTES-1.23 index 86bf6b1510..16bdf1e12e 100644 --- a/RELEASE-NOTES-1.23 +++ b/RELEASE-NOTES-1.23 @@ -220,6 +220,9 @@ changes to languages because of Bugzilla reports. 3 headings)" was removed. * (bug 52810) Preference "Justify paragraphs" was removed. * OutputPage::showErrorPage raises a notice if arguments are incoherent. +* Thumbnails that keep failing to render in thumb.php will be rate-limited + againt further render attempts for 1 hour. $wgAttemptFailureEpoch can be + altered to reset all rate-limited thumbnails at once. ==== Removed classes ==== * FakeMemCachedClient (deprecated in 1.18) diff --git a/includes/DefaultSettings.php b/includes/DefaultSettings.php index 536c035f31..bb80bebbab 100644 --- a/includes/DefaultSettings.php +++ b/includes/DefaultSettings.php @@ -1031,6 +1031,14 @@ $wgTiffThumbnailType = false; */ $wgThumbnailEpoch = '20030516000000'; +/** + * Certain operations are avoided if there were too many recent failures, + * for example, thumbnail generation. Bump this value to invalidate all + * memory of failed operations and thus allow further attempts to resume. + * This is useful when a cause for the failures has been found and fixed. + */ +$wgAttemptFailureEpoch = 1; + /** * If set, inline scaled images will still produce "" tags ready for * output instead of showing an error message. diff --git a/languages/messages/MessagesEn.php b/languages/messages/MessagesEn.php index 88b729d75f..5e92d3d13a 100644 --- a/languages/messages/MessagesEn.php +++ b/languages/messages/MessagesEn.php @@ -3577,6 +3577,7 @@ $2', 'thumbnail_image-type' => 'Image type not supported', 'thumbnail_gd-library' => 'Incomplete GD library configuration: Missing function $1', 'thumbnail_image-missing' => 'File seems to be missing: $1', +'thumbnail_image-failure-limit' => 'There have been too many recent failed attempts ($1 or more) to render this thumbnail. Please try again later.', # Special:Import 'import' => 'Import pages', diff --git a/languages/messages/MessagesQqq.php b/languages/messages/MessagesQqq.php index 88745071bd..b004b12def 100644 --- a/languages/messages/MessagesQqq.php +++ b/languages/messages/MessagesQqq.php @@ -7269,6 +7269,8 @@ See also: *$1 is a function name of the GD library', 'thumbnail_image-missing' => 'This is the parameter 1 of the message {{msg-mw|thumbnail error}}. *$1 is the path incl. filename of the missing image', +'thumbnail_image-failure-limit' => 'This is the parameter 1 of the message {{msg-mw|thumbnail error}}. +*$1 is the maximum allowed number of failed attempts', # Special:Import 'import' => 'The title of the special page [[Special:Import]];', @@ -9649,7 +9651,7 @@ Quotation marks, for quoting, sometimes titles etc., depending on the language. See: [[w:Non-English usage of quotation marks|Non-English usage of quotation marks on Wikipedia]]. -Parameters: +Parameters: * $1 - text to be wrapped in quotation marks', # Multipage image navigation diff --git a/maintenance/language/messages.inc b/maintenance/language/messages.inc index ed85223c37..6e6c3ed6c5 100644 --- a/maintenance/language/messages.inc +++ b/maintenance/language/messages.inc @@ -2490,6 +2490,7 @@ $wgMessageStructure = array( 'thumbnail_image-type', 'thumbnail_gd-library', 'thumbnail_image-missing', + 'thumbnail_image-failure-limit' ), 'import' => array( 'import', diff --git a/thumb.php b/thumb.php index ad5239e297..88aecbdbf9 100644 --- a/thumb.php +++ b/thumb.php @@ -307,6 +307,9 @@ function wfStreamThumb( array $params ) { if ( $user->pingLimiter( 'renderfile' ) ) { wfThumbError( 500, wfMessage( 'actionthrottledtext' ) ); return; + } elseif ( wfThumbIsAttemptThrottled( $img, $thumbName, 5 ) ) { + wfThumbError( 500, wfMessage( 'thumbnail_image-failure-limit', 5 ) ); + return; } // Thumbnail isn't already there, so create the new thumbnail... @@ -332,6 +335,7 @@ function wfStreamThumb( array $params ) { } if ( $errorMsg !== false ) { + wfThumbIncrAttemptFailures( $img, $thumbName ); wfThumbError( 500, $errorMsg ); } else { // Stream the file if there were no errors @@ -339,6 +343,45 @@ function wfStreamThumb( array $params ) { } } +/** + * @param File $img + * @param string $thumbName + * @param int $limit + * @return int|bool + */ +function wfThumbIsAttemptThrottled( File $img, $thumbName, $limit ) { + global $wgMemc; + + return ( $wgMemc->get( wfThumbAttemptKey( $img, $thumbName ) ) >= $limit ); +} + +/** + * @param File $img + * @param string $thumbName + */ +function wfThumbIncrAttemptFailures( File $img, $thumbName ) { + global $wgMemc; + + $key = wfThumbAttemptKey( $img, $thumbName ); + if ( !$wgMemc->incr( $key, 1 ) ) { + if ( !$wgMemc->add( $key, 1, 3600 ) ) { + $wgMemc->incr( $key, 1 ); + } + } +} + +/** + * @param File $img + * @param string $thumbName + * @return string + */ +function wfThumbAttemptKey( File $img, $thumbName ) { + global $wgAttemptFailureEpoch; + + return wfMemcKey( 'attempt-failures', $wgAttemptFailureEpoch, + $img->getRepo()->getName(), md5( $img->getName() ), md5( $thumbName ) ); +} + /** * Convert pathinfo type parameter, into normal request parameters * -- 2.20.1