Add back "final" to Drupal\big_pipe\StackMiddleware\ContentLength

Created on 3 January 2024, 12 months ago
Updated 2 March 2024, 10 months ago

Problem/Motivation

After the fix in πŸ› Regression from #3295790 content-length header set earlier than expected Fixed , running database updates via drush updb throws an uncaught exception. In πŸ› Uncaught exception thrown when running database updates via drush Active we worked around this by removing final. This issue is for adding

final<code> back.

The underlying issue is that lazy Symfony services do not support <code>final

classes, but this can be worked around with interface proxying:
https://symfony.com/doc/6.4/service_container/lazy_services.html#interface-proxifying

If there is more than one service tagged 'http_middleware' and at least one that is a responder, Drupal\Core\DependencyInjection\Compiler\StackedKernelPass::process() sets all those middleware services as lazy, other than the first responder.

The issue only seems to surface in Drupal (as observed so far) when the kernel's container is an instance of Symfony\Component\DependencyInjection\ContainerBuilder. The Drupal\Core\Update\UpdateKernel has its container set to an instance of ContainerBuilder, and the exception is thrown in the kernel terminate() method, when the call to ::getHttpKernel() leads to $this->container->get('http_kernel'), and as the decorated service is instantiated, the lazy middleware services are proxied, leading to an exception on final classes. Since this exception is thrown during the terminate phase, the exception is not displayed in browser when running updates via browser at update.php. The exception is logged, though. when running updates via drush, the exception stops the command from completing.

Proposed resolution

  1. Add back "final" to Drupal\big_pipe\StackMiddleware\ContentLength
  2. Add 'proxy' tags to http_middleware services set to lazy in Drupal\Core\DependencyInjection\Compiler\StackedKernelPass with the Symfony\Component\HttpKernel\HttpKernelInterface (and possibly Symfony\Component\HttpKernel\TerminableInterface) interfaces

Remaining tasks

User interface changes

API changes

Data model changes

Release notes snippet

πŸ› Bug report
Status

Fixed

Version

11.0 πŸ”₯

Component
BigPipeΒ  β†’

Last updated 3 days ago

Created by

πŸ‡¬πŸ‡§United Kingdom catch

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Merge Requests

Comments & Activities

  • Issue created by @catch
  • This might not be a drush issue? https://github.com/drush-ops/drush/issues/5848#issuecomment-1876021392

    From this part of the exception thrown documented in πŸ› Uncaught exception thrown when running database updates via drush Active ,
    ```
    Fatal error: Uncaught Symfony\Component\VarExporter\Exception\LogicException: Cannot generate lazy proxy: class "Drupal\big_pipe\StackMiddleware\ContentLength" is final. in /var/
    www/html/vendor/symfony/var-exporter/ProxyHelper.php:92
    Stack trace:
    #0 /var/www/html/vendor/symfony/dependency-injection/LazyProxy/PhpDumper/LazyServiceDumper.php(136): Symfony\Component\VarExporter\ProxyHelper::generateLazyProxy(Object(Reflectio
    nClass), Array)
    #1 /var/www/html/vendor/symfony/dependency-injection/LazyProxy/Instantiator/LazyServiceInstantiator.php(33): Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\LazyService
    Dumper->getProxyCode(Object(Symfony\Component\DependencyInjection\Definition), 'http_middleware...')
    #2 /var/www/html/vendor/symfony/dependency-injection/ContainerBuilder.php(1086): Symfony\Component\DependencyInjection\LazyProxy\Instantiator\LazyServiceInstantiator->instantiate
    ```

    Looked at Symfony docs for Lazy Services: https://symfony.com/doc/6.4/service_container/lazy_services.html, and saw this:

    Lazy services do not support final classes, but you can use Interface Proxifying to work around this limitation.

    In PHP versions prior to 8.0 lazy services do not support parameters with default values for built-in PHP classes (e.g. PDO).

    Suggestion there is to use interface proxying:

    # config/services.yaml
    services:
        App\Twig\AppExtension:
            lazy: 'Twig\Extension\ExtensionInterface'
            # or a complete definition:
            lazy: true
            tags:
                - { name: 'proxy', interface: 'Twig\Extension\ExtensionInterface' }
    
  • Opened MR 6017 as experiment to use interface proxying per previous comment in the service declaration. Ran drush updb with this change and saw saw no exceptions thrown and updates ran successfully.

    Not sure how to reproduce the exception otherwise, so leaving it here for now.

  • Status changed to Needs review 12 months ago
  • Turns out it's not a Drush-specific problem, and the error was not obvious on update.php because the exception was thrown during kernel->terminate() call after page was already sent to browser. Exception does show up in the log.

    Updated IS. Updated MR with proposed approach and added a unit test.

  • Status changed to RTBC 12 months ago
  • πŸ‡ΊπŸ‡ΈUnited States smustgrave

    Ran the test-only job

    1) Drupal\Tests\Core\DependencyInjection\Compiler\StackedKernelPassTest::testProcessWithStackedKernelAndFinalHttpMiddleware
    Cannot generate lazy proxy for service "http_kernel.two".
    /builds/issue/drupal-3412168/core/tests/Drupal/Tests/Core/DependencyInjection/Compiler/StackedKernelPassTest.php:151
    /builds/issue/drupal-3412168/vendor/phpunit/phpunit/src/Framework/TestResult.php:728
    /builds/issue/drupal-3412168/vendor/phpunit/phpunit/src/Framework/TestSuite.php:684
    /builds/issue/drupal-3412168/vendor/phpunit/phpunit/src/TextUI/TestRunner.php:651
    /builds/issue/drupal-3412168/vendor/phpunit/phpunit/src/TextUI/Command.php:144
    /builds/issue/drupal-3412168/vendor/phpunit/phpunit/src/TextUI/Command.php:97
    FAILURES!
    Tests: 3, Assertions: 15, Failures: 1.
    

    Issue summary proposed solution match the fix.

    Left a comment but that's just a curiosity and not a blocker if anyone see's that thread.

    Change LGTM!

  • Status changed to Needs work 12 months ago
  • πŸ‡¬πŸ‡§United Kingdom longwave UK

    Tiny whitespace nitpick otherwise this looks good to me.

  • First commit to issue fork.
  • Status changed to RTBC 12 months ago
  • Fixed whitespace. Moving back to RTBC since that was the only thing.

  • πŸ‡¬πŸ‡§United Kingdom longwave UK

    Decided not to backport as this isn't critical, if someone is doing something strange in 10.2 we won't break their code but they will have to fix for 10.3.

    Committed c10494d and pushed to 11.x. Thanks!

  • Status changed to Fixed 12 months ago
    • longwave β†’ committed c10494df on 11.x
      Issue #3412168 by godotislate, catch, smustgrave, longwave: Add back "...
  • Automatically closed - issue fixed for 2 weeks with no activity.

Production build 0.71.5 2024