Problems with cursor position escape #22460

Closed
opened 2026-01-31 08:13:58 +00:00 by claunia · 7 comments
Owner

Originally created by @cracyc on GitHub (Oct 27, 2024).

Originally assigned to: @lhecker on GitHub.

Windows Terminal version

1.22.2912.0

Windows build number

10.0.22631.4196

Other Software

https://github.com/cracyc/msdos-player/blob/vt/msdos.cpp#L1088

Steps to reproduce

Start it in a new console window or run in an existing one and execute a command with lots of output.

Expected Behavior

No response

Actual Behavior

When the program starts it immediately gets the console window size and the cursor position which hangs forever. If run from an existing console window it starts fine but if say command.com is run and dir then it will randomly hang waiting for the reply to ESC [6n, although it will resume after a bit or a key is pressed. This does not happen on terminal version 1.21.2911.0, in legacy conhost or if GetConsoleScreenBufferInfo is used instead.

Originally created by @cracyc on GitHub (Oct 27, 2024). Originally assigned to: @lhecker on GitHub. ### Windows Terminal version 1.22.2912.0 ### Windows build number 10.0.22631.4196 ### Other Software https://github.com/cracyc/msdos-player/blob/vt/msdos.cpp#L1088 ### Steps to reproduce Start it in a new console window or run in an existing one and execute a command with lots of output. ### Expected Behavior _No response_ ### Actual Behavior When the program starts it immediately gets the console window size and the cursor position which hangs forever. If run from an existing console window it starts fine but if say command.com is run and dir then it will randomly hang waiting for the reply to ESC [6n, although it will resume after a bit or a key is pressed. This does not happen on terminal version 1.21.2911.0, in legacy conhost or if GetConsoleScreenBufferInfo is used instead.
claunia added the Issue-BugNeeds-Tag-FixArea-ServerProduct-Conpty labels 2026-01-31 08:13:59 +00:00
Author
Owner

@shaymuiruri commented on GitHub (Oct 30, 2024):

I would love to work on this issue.

@shaymuiruri commented on GitHub (Oct 30, 2024): I would love to work on this issue.
Author
Owner

@carlos-zamora commented on GitHub (Oct 30, 2024):

Keeping the Triage tag on, but this may be of interest to @lhecker

@carlos-zamora commented on GitHub (Oct 30, 2024): Keeping the Triage tag on, but this may be of interest to @lhecker
Author
Owner

@carlos-zamora commented on GitHub (Nov 6, 2024):

Thanks for filing. A few questions from the team:

@carlos-zamora commented on GitHub (Nov 6, 2024): Thanks for filing. A few questions from the team: - Could you capture an ETL trace (see https://github.com/microsoft/terminal/wiki/Troubleshooting-Tips#capturing-a-debug-etl-trace) of the bug? - Is there a simpler way to repro this that doesn't require the attached ms-dos repo?
Author
Owner

@j4james commented on GitHub (Nov 6, 2024):

@carlos-zamora I'm not sure if this is exactly the same thing, but I can reproduce similar behavior with a batch file like this:

@echo 
@set /p "x=RESPONSE:"

NB: The  character is meant to be an escape.

If you run that from within an open terminal window, you'll get the expected DSR response looking something like this:

RESPONSE:^[[13;1R

But if you try and run the the script by double clicking on the file in Windows Explorer, it'll open up in the terminal, and you'll see the RESPONSE: prompt, but no actual DSR response.

Interestingly the problem appears to be specific to the CPR request. Other report sequences I tried (e.g. DA1) worked fine. I suspect we're sending out own CPR request as part of the conpty startup sequence and that possibly ends up grabbing the script's response as well.

@j4james commented on GitHub (Nov 6, 2024): @carlos-zamora I'm not sure if this is exactly the same thing, but I can reproduce similar behavior with a batch file like this: ```cmd @echo  @set /p "x=RESPONSE:" ``` NB: The `` character is meant to be an escape. If you run that from within an open terminal window, you'll get the expected `DSR` response looking something like this: ``` RESPONSE:^[[13;1R ``` But if you try and run the the script by double clicking on the file in Windows Explorer, it'll open up in the terminal, and you'll see the `RESPONSE:` prompt, but no actual `DSR` response. Interestingly the problem appears to be specific to the `CPR` request. Other report sequences I tried (e.g. `DA1`) worked fine. I suspect we're sending out own `CPR` request as part of the conpty startup sequence and that possibly ends up grabbing the script's response as well.
Author
Owner

@cracyc commented on GitHub (Nov 7, 2024):

This will hang it for me:

#define NOMINMAX
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <stdio.h>

static DWORD input_mode_old;

BOOL WINAPI ctrl_handler(DWORD) {
    SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), input_mode_old);
    TerminateProcess(GetCurrentProcess(), 0);
    return TRUE;
}

int main() {
    const HANDLE in = GetStdHandle(STD_INPUT_HANDLE);
    const HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);

    GetConsoleMode(in, &input_mode_old);
    SetConsoleMode(in, ENABLE_PROCESSED_INPUT | ENABLE_VIRTUAL_TERMINAL_INPUT);
    SetConsoleCtrlHandler(ctrl_handler, TRUE);

    for (unsigned long long i = 0;; i++) {
        wchar_t buf[128];
        DWORD buf_len = swprintf_s(buf, ARRAYSIZE(buf), L"%llu \x1b[6n", i);
        WriteConsoleW(out, buf, buf_len, NULL, NULL);

        if (!ReadConsoleW(in, buf, ARRAYSIZE(buf), &buf_len, NULL) || buf_len == 0) {
            break;
        }

        for (DWORD j = 0; j < buf_len; j++) {
            wchar_t ch = buf[j];
            if (ch < 0x20) {
                ch += 0x2400;
            } else if (ch == 0x20) {
                ch = 0x2423; // replace space with ␣
            } else if (ch == 0x7f) {
                ch = 0x2421; // replace del with ␡
            }
            buf[j] = ch;
        }

        buf[buf_len++] = L'\r';
        buf[buf_len++] = L'\n';
        WriteConsoleW(out, buf, buf_len, NULL, NULL);
    }

    SetConsoleMode(in, input_mode_old);
    return 0;
}
@cracyc commented on GitHub (Nov 7, 2024): This will hang it for me: ```cpp #define NOMINMAX #define WIN32_LEAN_AND_MEAN #include <Windows.h> #include <stdio.h> static DWORD input_mode_old; BOOL WINAPI ctrl_handler(DWORD) { SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), input_mode_old); TerminateProcess(GetCurrentProcess(), 0); return TRUE; } int main() { const HANDLE in = GetStdHandle(STD_INPUT_HANDLE); const HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE); GetConsoleMode(in, &input_mode_old); SetConsoleMode(in, ENABLE_PROCESSED_INPUT | ENABLE_VIRTUAL_TERMINAL_INPUT); SetConsoleCtrlHandler(ctrl_handler, TRUE); for (unsigned long long i = 0;; i++) { wchar_t buf[128]; DWORD buf_len = swprintf_s(buf, ARRAYSIZE(buf), L"%llu \x1b[6n", i); WriteConsoleW(out, buf, buf_len, NULL, NULL); if (!ReadConsoleW(in, buf, ARRAYSIZE(buf), &buf_len, NULL) || buf_len == 0) { break; } for (DWORD j = 0; j < buf_len; j++) { wchar_t ch = buf[j]; if (ch < 0x20) { ch += 0x2400; } else if (ch == 0x20) { ch = 0x2423; // replace space with ␣ } else if (ch == 0x7f) { ch = 0x2421; // replace del with ␡ } buf[j] = ch; } buf[buf_len++] = L'\r'; buf[buf_len++] = L'\n'; WriteConsoleW(out, buf, buf_len, NULL, NULL); } SetConsoleMode(in, input_mode_old); return 0; } ```
Author
Owner

@lhecker commented on GitHub (Nov 7, 2024):

That is an excellent repro! It really hangs almost immediately.
I've rewritten your example slightly though to make Ctrl-C work and get the terminal into the previous input mode when it exits. I also added some logic to make sure all possibly non-printables are escaped (just in case). Finally, I added a counter so that it's easier to spot when it stops.

@lhecker commented on GitHub (Nov 7, 2024): That is an excellent repro! It really hangs almost immediately. I've rewritten your example slightly though to make Ctrl-C work and get the terminal into the previous input mode when it exits. I also added some logic to make sure all possibly non-printables are escaped (just in case). Finally, I added a counter so that it's easier to spot when it stops.
Author
Owner

@cracyc commented on GitHub (Jun 11, 2025):

I can confirm that https://github.com/microsoft/terminal/pull/18816 does fix the problem with the msdos-player.

@cracyc commented on GitHub (Jun 11, 2025): I can confirm that https://github.com/microsoft/terminal/pull/18816 does fix the problem with the msdos-player.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/terminal#22460