? 955236-1_error_handling.patch ? 955236-2_error_handling.patch Index: feeds.module =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/feeds/feeds.module,v retrieving revision 1.74.2.11 diff -u -p -r1.74.2.11 feeds.module --- feeds.module 27 Oct 2010 19:53:21 -0000 1.74.2.11 +++ feeds.module 29 Oct 2010 19:35:28 -0000 @@ -738,6 +738,39 @@ function feeds_log($importer_id, $feed_n } /** + * Gets the last caller from a backtrace. + * + * Modeled after _drupal_get_last_caller(). + * + * @param $backtrace + * A standard PHP backtrace. + * @return + * An associative array with keys 'file', 'line' and 'function'. + */ +function feeds_get_last_caller($backtrace) { + // Shift off one to not report Feeds error handler methods. + array_shift($backtrace); + + // The first trace is the call itself. + // It gives us the line and the file of the last call. + $call = $backtrace[0]; + + // The second call give us the function where the call originated. + if (isset($backtrace[1])) { + if (isset($backtrace[1]['class'])) { + $call['function'] = $backtrace[1]['class'] . $backtrace[1]['type'] . $backtrace[1]['function'] . '()'; + } + else { + $call['function'] = $backtrace[1]['function'] . '()'; + } + } + else { + $call['function'] = 'main()'; + } + return $call; +} + +/** * Loads an item info object. * * Example usage: Index: includes/FeedsSource.inc =================================================================== RCS file: /cvs/drupal-contrib/contributions/modules/feeds/includes/FeedsSource.inc,v retrieving revision 1.26.2.8 diff -u -p -r1.26.2.8 FeedsSource.inc --- includes/FeedsSource.inc 26 Oct 2010 03:05:58 -0000 1.26.2.8 +++ includes/FeedsSource.inc 29 Oct 2010 19:35:29 -0000 @@ -328,6 +328,8 @@ class FeedsSource extends FeedsConfigura */ public function import() { $this->acquireLock(); + set_error_handler(array($this, 'importError')); + try { // Fetch. if (empty($this->fetcher_result) || FEEDS_BATCH_COMPLETE == $this->progressParsing()) { @@ -354,6 +356,8 @@ class FeedsSource extends FeedsConfigura unset($this->fetcher_result, $this->state); } $this->save(); + restore_error_handler(); + if (isset($e)) { throw $e; } @@ -376,6 +380,8 @@ class FeedsSource extends FeedsConfigura */ public function clear() { $this->acquireLock(); + set_error_handler(array($this, 'clearError')); + try { $this->importer->fetcher->clear($this); $this->importer->parser->clear($this); @@ -391,6 +397,8 @@ class FeedsSource extends FeedsConfigura unset($this->state); } $this->save(); + restore_error_handler(); + if (isset($e)) { throw $e; } @@ -398,6 +406,57 @@ class FeedsSource extends FeedsConfigura } /** + * Handles errors on import. + */ + public function importError($error_level, $message, $filename, $line, $context) { + if ($error_level & error_reporting()) { + // If this is NOT a recoverable error, attempt to clean up. + // @todo: does this make sense or do we know that if an error was not + // recoverable we can't clean up? + // @todo: it may be safer to delete the state every time when loading it. + if ($this->handleError($error_level, $message, $filename, $line, $context)) { + unset($this->state); + $this->save(); + } + _drupal_error_handler($error_level, $message, $filename, $line, $context); + } + } + + /** + * Handles errors on clear. + */ + public function clearError($error_level, $message, $filename, $line, $context) { + if ($error_level & error_reporting()) { + if ($this->handleError($error_level, $message, $filename, $line, $context)) { + unset($this->state); + $this->save(); + } + _drupal_error_handler($error_level, $message, $filename, $line, $context); + } + } + + /** + * Logs error and determines whether error is fatal + * + * @return + * TRUE if error is fatal, FALSE otherwise. + */ + protected function handleError($error_level, $message, $filename, $line, $context) { + require_once DRUPAL_ROOT . '/includes/errors.inc'; + $levels = drupal_error_levels(); + list ($severity_message, $severity_level) = $levels[$error_level]; + $caller = feeds_get_last_caller(debug_backtrace()); + $variables = array( + '@message' => $message, + '%function' => $caller['function'], + '%file' => $caller['file'], + '%line' => $caller['line'], + ); + $this->log('import', "@message
%function
%file
%line", $variables, $severity_level); + return $error_level & array(E_ERROR | E_COMPILE_ERROR | E_COMPILE_ERROR | E_USER_ERROR); + } + + /** * Report progress as float between 0 and 1. 1 = FEEDS_BATCH_COMPLETE. */ public function progressParsing() {