From 07f87cae782f6728ee1332c5f0c4d4ace37ad4d5 Mon Sep 17 00:00:00 2001
From: Lee Rowlands <lee.rowlands@previousnext.com.au>
Date: Wed, 9 Nov 2022 19:44:52 +1000
Subject: [PATCH] Issue #3319839 by alexpott: Exceptions in post updates are
 very broken since #3295625

---
 core/includes/update.inc                      |  2 +-
 .../post_update_test_failing.info.yml         |  5 ++
 .../post_update_test_failing.post_update.php  | 13 ++++
 .../UpdatePostUpdateExceptionTest.php         | 68 +++++++++++++++++++
 4 files changed, 87 insertions(+), 1 deletion(-)
 create mode 100644 core/modules/system/tests/modules/post_update_test_failing/post_update_test_failing.info.yml
 create mode 100644 core/modules/system/tests/modules/post_update_test_failing/post_update_test_failing.post_update.php
 create mode 100644 core/modules/system/tests/src/Functional/UpdateSystem/UpdatePostUpdateExceptionTest.php

diff --git a/core/includes/update.inc b/core/includes/update.inc
index 5aaeaaeb8a5f..1e9dd0d68c93 100644
--- a/core/includes/update.inc
+++ b/core/includes/update.inc
@@ -247,7 +247,7 @@ function update_invoke_post_update($function, &$context) {
       watchdog_exception('update', $e);
 
       $variables = Error::decodeException($e);
-      unset($variables['backtrace'], $variables['exception']);
+      unset($variables['backtrace'], $variables['exception'], $variables['severity_level']);
       $ret['#abort'] = [
         'success' => FALSE,
         'query' => t(Error::DEFAULT_ERROR_MESSAGE, $variables),
diff --git a/core/modules/system/tests/modules/post_update_test_failing/post_update_test_failing.info.yml b/core/modules/system/tests/modules/post_update_test_failing/post_update_test_failing.info.yml
new file mode 100644
index 000000000000..2dbbb5861207
--- /dev/null
+++ b/core/modules/system/tests/modules/post_update_test_failing/post_update_test_failing.info.yml
@@ -0,0 +1,5 @@
+name: 'Post Update test failing'
+type: module
+description: 'Support module for update testing when a post update is failing.'
+package: Testing
+version: VERSION
diff --git a/core/modules/system/tests/modules/post_update_test_failing/post_update_test_failing.post_update.php b/core/modules/system/tests/modules/post_update_test_failing/post_update_test_failing.post_update.php
new file mode 100644
index 000000000000..3cd6397f7118
--- /dev/null
+++ b/core/modules/system/tests/modules/post_update_test_failing/post_update_test_failing.post_update.php
@@ -0,0 +1,13 @@
+<?php
+
+/**
+ * @file
+ * Post update functions for test module.
+ */
+
+/**
+ * Post update that throws an exception.
+ */
+function post_update_test_failing_post_update_exception() {
+  throw new \RuntimeException('This post update fails');
+}
diff --git a/core/modules/system/tests/src/Functional/UpdateSystem/UpdatePostUpdateExceptionTest.php b/core/modules/system/tests/src/Functional/UpdateSystem/UpdatePostUpdateExceptionTest.php
new file mode 100644
index 000000000000..7248c91a5805
--- /dev/null
+++ b/core/modules/system/tests/src/Functional/UpdateSystem/UpdatePostUpdateExceptionTest.php
@@ -0,0 +1,68 @@
+<?php
+
+namespace Drupal\Tests\system\Functional\UpdateSystem;
+
+use Drupal\Core\Database\Database;
+use Drupal\Tests\BrowserTestBase;
+use Drupal\Tests\UpdatePathTestTrait;
+
+/**
+ * Tests hook_post_update() when there is an exception in a post update.
+ *
+ * @group Update
+ */
+class UpdatePostUpdateExceptionTest extends BrowserTestBase {
+  use UpdatePathTestTrait;
+
+  /**
+   * {@inheritdoc}
+   */
+  protected $defaultTheme = 'stark';
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp(): void {
+    parent::setUp();
+    $connection = Database::getConnection();
+
+    // Set the schema version.
+    \Drupal::service('update.update_hook_registry')->setInstalledVersion('post_update_test_failing', 8000);
+
+    // Update core.extension.
+    $extensions = $connection->select('config')
+      ->fields('config', ['data'])
+      ->condition('collection', '')
+      ->condition('name', 'core.extension')
+      ->execute()
+      ->fetchField();
+    $extensions = unserialize($extensions);
+    $extensions['module']['post_update_test_failing'] = 8000;
+    $connection->update('config')
+      ->fields([
+        'data' => serialize($extensions),
+      ])
+      ->condition('collection', '')
+      ->condition('name', 'core.extension')
+      ->execute();
+  }
+
+  /**
+   * Tests hook_post_update_NAME().
+   */
+  public function testPostUpdate() {
+    // There are expected to be failed updates.
+    $this->checkFailedUpdates = FALSE;
+
+    $this->runUpdates();
+    $this->assertSession()->pageTextContains('Failed: RuntimeException: This post update fails in post_update_test_failing_post_update_exception()');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function doSelectionTest() {
+    $this->assertSession()->assertEscaped("Post update that throws an exception.");
+  }
+
+}
-- 
GitLab