After each cache clear, visiting a page filtered with markdown causes calls to pecl.php.net; it is not clear why we are doing this

Created on 8 April 2022, over 2 years ago
Updated 11 September 2023, over 1 year ago

Problem/Motivation

When you clear cache and then visit a page with content using markdown, as part of the render process, markdown makes calls to:

* https://pecl.php.net/rest/r/cmark/allreleases.xml
* https://pecl.php.net/rest/r/cmark/package.1.2.0.xml

You can see the call graph in the enclosed png.

If the pecl.php.net server is slow, this slows down the entire process of rendering a page.

If the call to pecl.php.net causes an error or if one is doing local development without access to the internet, this causes the whole page to fail with the following error:

The website encountered an unexpected error. Please try again later.

Exception: Serialization of 'Closure' is not allowed in serialize() (line 152 of core/lib/Drupal/Component/Annotation/Plugin/Discovery/AnnotatedClassDiscovery.php).
Drupal\Component\Annotation\Plugin\Discovery\AnnotatedClassDiscovery->getDefinitions() (Line: 86)
Drupal\Component\Plugin\Discovery\DerivativeDiscoveryDecorator->getDefinitions() (Line: 213)
Drupal\markdown\PluginManager\InstallablePluginManager->findDefinitions() (Line: 175)
Drupal\Core\Plugin\DefaultPluginManager->getDefinitions() (Line: 384)
Drupal\markdown\PluginManager\InstallablePluginManager->getRuntimeDefinitions() (Line: 351)
Drupal\markdown\PluginManager\InstallablePluginManager->getDefinitions() (Line: 22)
Drupal\Core\Plugin\DefaultPluginManager->getDefinition('commonmark') (Line: 16)
Drupal\Core\Plugin\Factory\ContainerFactory->createInstance('commonmark', Array) (Line: 76)
Drupal\Component\Plugin\PluginManagerBase->createInstance('commonmark', Array) (Line: 202)
Drupal\markdown\PluginManager\InstallablePluginManager->createInstance('commonmark', Array) (Line: 67)
Drupal\markdown\PluginManager\ParserManager->createInstance('commonmark', Array) (Line: 221)
Drupal\markdown\Plugin\Filter\FilterMarkdown->setConfiguration(Array) (Line: 54)
Drupal\filter\Plugin\FilterBase->__construct(Array, 'markdown', Array) (Line: 70)
Drupal\markdown\Plugin\Filter\FilterMarkdown->__construct(Array, 'markdown', Array, Object, Object) (Line: 82)
Drupal\markdown\Plugin\Filter\FilterMarkdown::create(Object, Array, 'markdown', Array) (Line: 21)
Drupal\Core\Plugin\Factory\ContainerFactory->createInstance('markdown', Array) (Line: 76)
Drupal\Component\Plugin\PluginManagerBase->createInstance('markdown', Array) (Line: 81)
Drupal\Core\Plugin\DefaultLazyPluginCollection->initializePlugin('markdown') (Line: 76)
Drupal\filter\FilterPluginCollection->initializePlugin('markdown') (Line: 54)
Drupal\filter\FilterPluginCollection->getAll() (Line: 83)
Drupal\filter\FilterPluginCollection->sort() (Line: 144)
Drupal\filter\Entity\FilterFormat->filters() (Line: 50)
markdown_filter_format_load(Array) (Line: 438)
Drupal\Core\Entity\EntityStorageBase->postLoad(Array) (Line: 353)
Drupal\Core\Entity\EntityStorageBase->loadMultiple(Array) (Line: 296)
Drupal\Core\Entity\EntityStorageBase->load('full_html') (Line: 488)
Drupal\Core\Entity\EntityBase::load('full_html') (Line: 81)
Drupal\filter\Element\ProcessedText::preRenderText(Array)
call_user_func_array(Array, Array) (Line: 101)
Drupal\Core\Render\Renderer->doTrustedCallback(Array, Array, 'Render #pre_render callbacks must be methods of a class that implements \Drupal\Core\Security\TrustedCallbackInterface or be an anonymous function. The callback was %s. See https://www.drupal.org/node/2966725', 'exception', 'Drupal\Core\Render\Element\RenderCallbackInterface') (Line: 772)
Drupal\Core\Render\Renderer->doCallback('#pre_render', Array, Array) (Line: 363)
Drupal\Core\Render\Renderer->doRender(Array, ) (Line: 201)
Drupal\Core\Render\Renderer->render(Array) (Line: 479)
Drupal\Core\Template\TwigExtension->escapeFilter(Object, Array, 'html', NULL, 1) (Line: 88)
__TwigTemplate_e1738a5577b26df957bd9709baed488280a9355d9864e4f823794c6edbb864b9->doDisplay(Array, Array) (Line: 405)
Twig\Template->displayWithErrorHandling(Array, Array) (Line: 378)
Twig\Template->display(Array, Array) (Line: 46)
__TwigTemplate_8f11099aa3a9bf3ce0b4273b5fdca91ce2dbf678fbf6ce47fa413ca51a6f0e27->doDisplay(Array, Array) (Line: 405)
Twig\Template->displayWithErrorHandling(Array, Array) (Line: 378)
Twig\Template->display(Array, Array) (Line: 43)
__TwigTemplate_3a8db9ece1304a6994c61fcf3bbf1228921ec77f75b56641fcf4be422ccd52b2->doDisplay(Array, Array) (Line: 405)
Twig\Template->displayWithErrorHandling(Array, Array) (Line: 378)
Twig\Template->display(Array) (Line: 390)
Twig\Template->render(Array) (Line: 55)
twig_render_template('core/themes/bartik/templates/classy/field/field--text-with-summary.html.twig', Array) (Line: 384)
Drupal\Core\Theme\ThemeManager->render('field', Array) (Line: 422)
Drupal\Core\Render\Renderer->doRender(Array) (Line: 435)
Drupal\Core\Render\Renderer->doRender(Array, ) (Line: 201)
Drupal\Core\Render\Renderer->render(Array) (Line: 479)
Drupal\Core\Template\TwigExtension->escapeFilter(Object, Array, 'html', NULL, 1) (Line: 110)
__TwigTemplate_fcb7e0b3a292c6a4411aed00c164f5d7ae74e877d0b9050c32ab9d3e043b998f->doDisplay(Array, Array) (Line: 405)
Twig\Template->displayWithErrorHandling(Array, Array) (Line: 378)
Twig\Template->display(Array) (Line: 390)
Twig\Template->render(Array) (Line: 55)
twig_render_template('core/themes/bartik/templates/node.html.twig', Array) (Line: 384)
Drupal\Core\Theme\ThemeManager->render('node', Array) (Line: 422)
Drupal\Core\Render\Renderer->doRender(Array, ) (Line: 201)
Drupal\Core\Render\Renderer->render(Array, ) (Line: 241)
Drupal\Core\Render\MainContent\HtmlRenderer->Drupal\Core\Render\MainContent\{closure}() (Line: 564)
Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 242)
Drupal\Core\Render\MainContent\HtmlRenderer->prepare(Array, Object, Object) (Line: 132)
Drupal\Core\Render\MainContent\HtmlRenderer->renderResponse(Array, Object, Object) (Line: 90)
Drupal\Core\EventSubscriber\MainContentViewSubscriber->onViewRenderArray(Object, 'kernel.view', Object)
call_user_func(Array, Object, 'kernel.view', Object) (Line: 142)
Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch(Object, 'kernel.view') (Line: 163)
Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 80)
Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 58)
Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 106)
Drupal\page_cache\StackMiddleware\PageCache->pass(Object, 1, 1) (Line: 85)
Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 51)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 23)
Stack\StackedHttpKernel->handle(Object, 1, 1) (Line: 708)
Drupal\Core\DrupalKernel->handle(Object) (Line: 19)

It is not clear why a working installation of markdown needs to make calls to pecl.php.net.

Steps to reproduce

Install Drupal 9.3.9, then run:

composer require league/commonmark:^1.0 drupal/markdown:^3
drush site:install -y
mkdir -p sites/default/files/installable_plugins/library
chown -R www-data:www-data sites/default/files/installable_plugins/library
drush pm:enable -y markdown
drush cache:rebuild

Then log in as user 1

Then go to /admin/config/content/markdown

Confirm you see "CommonMark (default)" and no errors.

Then go to /admin/reports/status

Confirm there are no errors

Then go to /admin/config/content/formats/manage/full_html

Uncheck the "Correct faulty and chopped off HTML" filter

Check the "Markdown" filter

Save configuration

Go to /node/add/article

Title: "Test", Body: "Test", text format: "Full HTML"

Then click Save.

Install the XDebug PHP profiler and the Webgrind Profiler viewer (these are included in https://github.com/dcycle/starterkit-drupalsite, see instructions therein for use with Docker).

drush cache:rebuild

Then visit /node/1?XDEBUG_PROFILE=1

Then visit the profiling information graph (enclosed as a PNG), notice that calls are being made to curl_exec.

Proposed resolution

Do not make calls to pecl.php.net as part of the formatting process.

Remaining tasks

User interface changes

API changes

Data model changes

πŸ› Bug report
Status

Active

Version

3.0

Component

Code

Created by

πŸ‡¨πŸ‡¦Canada alberto56

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

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • September 2023 - this issue has surfaced again for several of our team members at once, in separate physical locations.

    MR 18 containing patch https://git.drupalcode.org/project/markdown/-/commit/02425a6ef054376c0d8... still applies for markdown 3.0.0 and still fixes / works around the issue.

  • πŸ‡¬πŸ‡§United Kingdom malcomio

    The error has started happening again because the certificate has expired.

    As noted in the code comment in the merge request, ideally this would not be happening for each page request.

  • πŸ‡ΊπŸ‡ΈUnited States eojthebrave Minneapolis, MN

    Chiming in to say I also ran into this this morning. The patch in #7 works as a quick fix. I also was first seeing this error in my PHP logs which ultimately led here. Adding the error for anyone else searching for this issue.

    Uncaught PHP Exception Exception: "Serialization of 'Closure' is not allowed" at /code/web/core/lib/Drupal/Component/Annotation/Plugin/Discovery/AnnotatedClassDiscovery.php line 152

Production build 0.71.5 2024