Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Requests leave stopwatch section open #36623

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
uncaught opened this issue Apr 29, 2020 · 15 comments
Closed

Requests leave stopwatch section open #36623

uncaught opened this issue Apr 29, 2020 · 15 comments

Comments

@uncaught
Copy link
Contributor

uncaught commented Apr 29, 2020

Symfony version(s) affected: 3.4 up till current master

Description
When making a request, the TraceableEventDispatcher opens a section with the Stopwatch, which never gets closed.

This causes a \LogicException when measuring the time of something with an internal requests.

How to reproduce

$stopwatch->start('foo');
// do something with an internal request:
$kernel->handle($subRequest, HttpKernelInterface::SUB_REQUEST, false);
$stopwatch->stop('foo');

--> yields \LogicException('Event "foo" is not started.') in the last line

Possible Solution
Call stopSection even if no 'X-Debug-Token' is set in the response headers.

The route name might be a neat fallback:

$token = $event->getResponse()->headers->get('X-Debug-Token', $event->getRequest()->attributes->get('_route'));

The TraceableEventDispatcher starts the section, it should be responsible for it being closed again, no matter what.

Additional context
This happens running a functional test with phpunit with debug enabled.

The only place where 'X-Debug-Token' is set seems to be the Profiler - which is probably not enabled during unit tests (at least for us).

@uncaught uncaught added the Bug label Apr 29, 2020
Tobion referenced this issue in symfony/http-kernel May 11, 2020
the toolbar and profiler panel disable to profiler which then does not set the X-Debug-Token. so when the header does not exist, do not call the stopwatch methods with null which violates the contract and does not make sense
@mpoiriert
Copy link

This seems to be the commit that introduce the bug.

symfony/http-kernel@7b2421a

But on the logic of the Stopwatch::stopSection is not good it's just pop the last active section assuming that the id match. There is no check that the start end stop are done in the proper order.

    public function stopSection(string $id)
    {
        $this->stop('__section__');

        if (1 == \count($this->activeSections)) {
            throw new \LogicException('There is no started section to stop.');
        }

        $this->sections[$id] = array_pop($this->activeSections)->setId($id);
        $this->stop('__section__.child');
    }

@carsonbot
Copy link

Hey, thanks for your report!
There has not been a lot of activity here for a while. Is this bug still relevant? Have you managed to find a workaround?

@carsonbot
Copy link

Could I get a reply or should I close this?

@uncaught
Copy link
Contributor Author

uncaught commented Mar 5, 2021

If not using the profiler is a workaround, then yes.

Otherwise it is still broken.

@carsonbot carsonbot removed the Stalled label Mar 5, 2021
@BafS
Copy link
Contributor

BafS commented Jul 7, 2021

@uncaught may I ask what is your workaround ? I have the same issue.

@uncaught
Copy link
Contributor Author

uncaught commented Jul 7, 2021

I think I simply used microtime() to measure the time manually back then. Sorry, not really a workaround.

@xabbuh
Copy link
Member

xabbuh commented Jul 7, 2021

Can you create a small example application that allows to reproduce your issue?

@jlekowski
Copy link
Contributor

Can you create a small example application that allows to reproduce your issue?

@xabbuh, that has been fixed in #39598.
Another ticket I created is #36762 with a link to virtually the same code fix. Tested locally and seems to be working since Symfony 5.1.

@mpoiriert
Copy link

@jlekowski This is not related to the messenger but the http kernel.

I have gave the exact line of the class where the issue is and also pin point the commit where the issue was introduced. Hard to be more clear than that. #36623 (comment)

@jlekowski
Copy link
Contributor

True @mpoiriert, that fix did not target the root cause.

@xabbuh
Copy link
Member

xabbuh commented Jul 15, 2021

Well, without a reproducer that allows us to debug the issue in more detail I am afraid it's hard to help.

@jlekowski
Copy link
Contributor

@xabbuh, a command like this is probably the simplest way to reproduce it (just run bin/console test).

<?php

namespace App\Command;

use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Component\Stopwatch\Stopwatch;

class TestCommand extends Command
{
    /**
     * @var KernelInterface
     */
    private $kernel;

    /**
     * @var Stopwatch
     */
    private $stopwatch;

    /**
     * @param KernelInterface $kernel
     */
    public function __construct(KernelInterface $kernel, Stopwatch $stopwatch)
    {
        $this->kernel = $kernel;
        $this->stopwatch = $stopwatch;
        parent::__construct('test');
    }

    /**
     * @param InputInterface $input
     * @param OutputInterface $output
     * @return int
     */
    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $this->stopwatch->start('foo');
        $this->kernel->handle(new Request(), HttpKernelInterface::SUB_REQUEST);
        $this->stopwatch->stop('foo');
        return 0;
    }
}

@mpoiriert
Copy link

mpoiriert commented Jul 16, 2021 via email

@xabbuh
Copy link
Member

xabbuh commented Jul 30, 2021

see #42331 for an attempt to fix this, please give it a try and provide some feedback if that PR fixes your issue

@jlekowski
Copy link
Contributor

@xabbuh, I tested your fix on my example code and it worked - the section stays open after running a sub-request.

@fabpot fabpot closed this as completed Aug 6, 2021
fabpot added a commit that referenced this issue Aug 6, 2021
…dling `kernel.request` events (xabbuh)

This PR was merged into the 4.4 branch.

Discussion
----------

[HttpKernel] always close open stopwatch section after handling `kernel.request` events

| Q             | A
| ------------- | ---
| Branch?       | 4.4
| Bug fix?      | yes
| New feature?  | no
| Deprecations? | no
| Tickets       | Fix #36623
| License       | MIT
| Doc PR        |

Commits
-------

705f765 always close open stopwatch section after handling kernel.request events
herndlm added a commit to herndlm/symfony that referenced this issue Sep 1, 2021
In order for the TimeDataCollector to work properly the X-Debug-Token from the response header needs to be used which was removed in symfony#42331 to fix symfony#36623. Fixes symfony#42804
herndlm added a commit to herndlm/symfony that referenced this issue Sep 1, 2021
In order for the `TimeDataCollector` to work properly the `X-Debug-Token` from the response header needs to be used which was removed in symfony#42331 to fix symfony#36623. Fixes symfony#42804
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants