Skip to content

Console QuestionHelper autocompelte does not restore stty on SIGINT #27786

Closed
@rtek

Description

@rtek

Symfony version(s) affected: 4.1

Description
If the user sends a SIGINT (CTRL+C) during the autocomplete phase of question ask, the stty will not be restored to its original state. This means that the console will not echo as the user types until they type stty echo (which they cannot see).

How to reproduce
This applies to linux and windows but I only created a test for windows.

This is a disaster of a test case because I needed to mock out shell_exec & stty somehow... 🤷‍♂️

//as part of QuestionHelperTest
    /**
     * @runInSeparateProcess
     */
    public function testAskWithAutocompleteRestoresSttyOnSigInt()
    {
        if(DIRECTORY_SEPARATOR === '/') {
            $this->markTestSkipped('Must run in windows');
        }

        $tempDir = getcwd().'/__temp';
        @mkdir($tempDir);
        chdir($tempDir);

        //this writes the stty arguments to the test file for inspection and returns a mode=restored for stty -g
        $sttyMock = "@echo off\r\necho \"%0 %*\" > stty.out\r\necho|set /p dummy=restored";
        file_put_contents('stty.bat', $sttyMock);

        register_shutdown_function(function() use ($tempDir) {
            $this->assertContains('restored', file_get_contents($tempDir . '/stty.out'));
        });

        $dialog = new QuestionHelper();
        $question = new Question('How are you');
        $question->setAutocompleterValues(array('Good', 'Bad'));

        //force an exit when ! is detected in the input stream
        $output = new class extends Output {
            protected function doWrite($message, $newline)
            {
                if($message === '!') {
                    exit(1); //simulate a CTRL-C
                }
            }
        };

        $dialog->ask($this->createStreamableInputInterfaceMock($this->getInputStream('ABC!123')), $output, $question);
    }
1) Symfony\Component\Console\Tests\Helper\QuestionHelperTest::testAskWithAutocompleteRestoresSttyOnSigInt
PHPUnit\Framework\Exception: PHP Fatal error:  Uncaught Failed asserting that '"stty -icanon -echo" \r\n
' contains "restored".

Possible Solution
register_shutdown_function can be used to add a handler that will restore the stty mode if it is not restored successfully. I looked into pcntl_signal but it does not allow multiple handlers.

SIGINT seems to cause shutdown functions to not be called?

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions