* Ctrl+C is sometimes ignored on Windows Terminal
@ 2021-11-01 8:33 Naoto Aoki
2021-11-01 8:50 ` Russell VT
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: Naoto Aoki @ 2021-11-01 8:33 UTC (permalink / raw)
To: cygwin
[-- Attachment #1: Type: text/plain, Size: 1148 bytes --]
Hi,
When I'm using some programs such as bash and python from cygwin under
Windows Terminal, Ctrl+C is sometimes ignored.
https://github.com/microsoft/terminal
Normally holding 'Ctrl' and pressing 'C' will make new line.
But, sometimes it does not and unholding 'Ctrl' makes new line under
Windows Terminal.
bash from msys2 does also reproduce this issue.
I dug into this issue and found that this is related to
readline and Windows 10's pseudo console (ConPTY).
I made simple programs to reproduce this issue.
- EchoCon.cpp
- modification of ConPty sample code provided by Microsoft.
This program execute bash on pseudo console.
to be compiled with MSVC.
- getkey.cpp
- simple program to check Ctrl+C is passed to Cygwin program.
to be compiled with Cygwin gcc.
- rltest.cpp
- simple program to check SIGINT handling.
This program reproduces the issue.
If you replace readline("> ") with gets(buf),
then the issue does not happen.
to be compiled with Cygwin gcc.
- The machine and OS that it is running on
- OS: Windows 10 Pro 19043.1288
- Windows Terminal: 1.11.2921.0
Regards,
Naoto Aoki
[-- Attachment #2: getkey.cpp --]
[-- Type: text/plain, Size: 2003 bytes --]
// original: https://blog.goo.ne.jp/lm324/e/16629a8aadaa0de77fc05611390cf15b
// modified by aont 2021/10/15
#include <stdio.h>
#include <stdlib.h>
#include <termios.h>
#include <unistd.h>
#include <signal.h>
#include <fcntl.h>
int getkey(void)
{
struct termios oldt, newt;
int ch0,ch1,ch2,ch3,ch4;
int ret;
tcgetattr(STDIN_FILENO, &oldt);
newt = oldt;
newt.c_iflag = ~( BRKINT | ISTRIP | IXON );
newt.c_lflag = ~( ICANON | IEXTEN | ECHO | ECHOE | ECHOK | ECHONL );
newt.c_cc[VTIME] = 0;
newt.c_cc[VMIN] = 1;
newt.c_cc[VINTR] = 1;
if(tcsetattr(STDIN_FILENO, TCSANOW, &newt)==-1) {
fprintf(stderr,"error tcsetattr\n");
exit(EXIT_FAILURE);
}
ch0 = getchar();
if(ch0==0x1B) {
ch1 = getchar();
ch2 = getchar();
if(ch2==0x32) {
ch3 = getchar();
if(ch3==0x7e) {
ret = (ch0<<24) | (ch1<<16) | (ch2<<8) | ch3;
} else {
ch4 = getchar();
ret = (ch1<<24) | (ch2<<16) | (ch3<<8) | ch4;
}
} else if(ch2==0x31) {
ch3 = getchar();
ch4 = getchar();
ret = (ch1<<24) | (ch2<<16) | (ch3<<8) | ch4;
} else if((ch2==0x33)||(ch2==0x35)||(ch2==0x36)) {
ch3 = getchar();
ret = (ch0<<24) | (ch1<<16) | (ch2<<8) | ch3;
} else {
ret = (ch0<<16) | (ch1<<8) | ch2;
}
} else if(ch0 != EOF) {
ret = ch0;
} else {
ret = 0;
}
if(tcsetattr(STDIN_FILENO, TCSANOW, &oldt)==-1) {
fprintf(stderr,"error tcsetattr\n");
exit(EXIT_FAILURE);
}
return ret;
}
int main(int argc,char *argv[])
{
int key;
while (1) {
key = getkey();
if (key!=0) {
printf("key code 0x%x\n",key);
}else{
;
usleep(1000);
}
if(key==0x71 /* q */ ) {
break;
}
}
return 0;
}
[-- Attachment #3: rltest.cpp --]
[-- Type: text/plain, Size: 577 bytes --]
#include <setjmp.h>
#include <stdio.h>
#include <signal.h>
#include <readline/readline.h>
sigjmp_buf ctrlc_buf;
void handle_signals(int signo) {
if (signo == SIGINT) {
siglongjmp(ctrlc_buf, 1);
}
}
int main(int argc, char **argv)
{
char * input;
if (signal(SIGINT, handle_signals) == SIG_ERR) {
fprintf(stderr, "installing signal handler failed\n");
}
char buf[128];
while (1)
{
while ( sigsetjmp( ctrlc_buf, 1 ) != 0 ) {
fprintf(stderr, "Ctrl+C\n");
}
input = readline("> ");
if (!input)
break;
}
return 0;
}
[-- Attachment #4: EchoCon.cpp --]
[-- Type: text/plain, Size: 7856 bytes --]
// EchoCon.cpp : Entry point for the EchoCon Pseudo-Console sample application.
// Copyright © 2018, Microsoft
// Modified by aont 2021/10/15
// #include "stdafx.h"
#include <Windows.h>
#include <process.h>
#include <cstdio>
// Forward declarations
HRESULT CreatePseudoConsoleAndPipes(HPCON*, HANDLE*, HANDLE*);
HRESULT InitializeStartupInfoAttachedToPseudoConsole(STARTUPINFOEX*, HPCON);
void __cdecl PipeListener(LPVOID);
int main()
{
wchar_t szCommand[]{ L"C:\\cygwin64\\bin\\bash.exe --login -i" };
HRESULT hr{ E_UNEXPECTED };
HANDLE hConsole = { GetStdHandle(STD_OUTPUT_HANDLE) };
HANDLE hin = GetStdHandle(STD_INPUT_HANDLE);
// Enable Console VT Processing
DWORD consoleMode{};
GetConsoleMode(hin, &consoleMode);
hr = SetConsoleMode(hin, consoleMode ^ ENABLE_PROCESSED_INPUT ^ ENABLE_LINE_INPUT)
? S_OK
: GetLastError();
GetConsoleMode(hConsole, &consoleMode);
hr = SetConsoleMode(hConsole, consoleMode | ENABLE_VIRTUAL_TERMINAL_PROCESSING)
? S_OK
: GetLastError();
if (S_OK == hr)
{
HPCON hPC{ INVALID_HANDLE_VALUE };
// Create the Pseudo Console and pipes to it
HANDLE hPipeIn{ INVALID_HANDLE_VALUE };
HANDLE hPipeOut{ INVALID_HANDLE_VALUE };
hr = CreatePseudoConsoleAndPipes(&hPC, &hPipeIn, &hPipeOut);
if (S_OK == hr)
{
// Create & start thread to listen to the incoming pipe
// Note: Using CRT-safe _beginthread() rather than CreateThread()
HANDLE hPipeListenerThread{ reinterpret_cast<HANDLE>(_beginthread(PipeListener, 0, hPipeIn)) };
// Initialize the necessary startup info struct
STARTUPINFOEX startupInfo{};
if (S_OK == InitializeStartupInfoAttachedToPseudoConsole(&startupInfo, hPC))
{
// Launch ping to emit some text back via the pipe
PROCESS_INFORMATION piClient{};
hr = CreateProcess(
NULL, // No module name - use Command Line
szCommand, // Command Line
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
FALSE, // Inherit handles
EXTENDED_STARTUPINFO_PRESENT, // Creation flags
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&startupInfo.StartupInfo, // Pointer to STARTUPINFO
&piClient) // Pointer to PROCESS_INFORMATION
? S_OK
: GetLastError();
char input_key;
DWORD num_events;
while (true) {
bool ret;
ret = ReadFile(hin, &input_key, 1, &num_events, NULL);
if (ret) {
fprintf(stderr, "input: 0x%x\n", input_key);
WriteFile(hPipeOut, &input_key, 1, &num_events, NULL);
}
};
if (S_OK == hr)
{
// Wait up to 10s for ping process to complete
WaitForSingleObject(piClient.hThread, 10 * 1000);
// Allow listening thread to catch-up with final output!
Sleep(500);
}
// --- CLOSEDOWN ---
// Now safe to clean-up client app's process-info & thread
CloseHandle(piClient.hThread);
CloseHandle(piClient.hProcess);
// Cleanup attribute list
DeleteProcThreadAttributeList(startupInfo.lpAttributeList);
free(startupInfo.lpAttributeList);
}
// Close ConPTY - this will terminate client process if running
ClosePseudoConsole(hPC);
// Clean-up the pipes
if (INVALID_HANDLE_VALUE != hPipeOut) CloseHandle(hPipeOut);
if (INVALID_HANDLE_VALUE != hPipeIn) CloseHandle(hPipeIn);
}
}
return S_OK == hr ? EXIT_SUCCESS : EXIT_FAILURE;
}
HRESULT CreatePseudoConsoleAndPipes(HPCON* phPC, HANDLE* phPipeIn, HANDLE* phPipeOut)
{
HRESULT hr{ E_UNEXPECTED };
HANDLE hPipePTYIn{ INVALID_HANDLE_VALUE };
HANDLE hPipePTYOut{ INVALID_HANDLE_VALUE };
// Create the pipes to which the ConPTY will connect
if (CreatePipe(&hPipePTYIn, phPipeOut, NULL, 0) &&
CreatePipe(phPipeIn, &hPipePTYOut, NULL, 0))
{
// Determine required size of Pseudo Console
COORD consoleSize{};
CONSOLE_SCREEN_BUFFER_INFO csbi{};
HANDLE hConsole{ GetStdHandle(STD_OUTPUT_HANDLE) };
if (GetConsoleScreenBufferInfo(hConsole, &csbi))
{
consoleSize.X = csbi.srWindow.Right - csbi.srWindow.Left + 1;
consoleSize.Y = csbi.srWindow.Bottom - csbi.srWindow.Top + 1;
}
// Create the Pseudo Console of the required size, attached to the PTY-end of the pipes
hr = CreatePseudoConsole(consoleSize, hPipePTYIn, hPipePTYOut, 0, phPC);
// Note: We can close the handles to the PTY-end of the pipes here
// because the handles are dup'ed into the ConHost and will be released
// when the ConPTY is destroyed.
if (INVALID_HANDLE_VALUE != hPipePTYOut) CloseHandle(hPipePTYOut);
if (INVALID_HANDLE_VALUE != hPipePTYIn) CloseHandle(hPipePTYIn);
}
return hr;
}
// Initializes the specified startup info struct with the required properties and
// updates its thread attribute list with the specified ConPTY handle
HRESULT InitializeStartupInfoAttachedToPseudoConsole(STARTUPINFOEX* pStartupInfo, HPCON hPC)
{
HRESULT hr{ E_UNEXPECTED };
if (pStartupInfo)
{
SIZE_T attrListSize{};
pStartupInfo->StartupInfo.cb = sizeof(STARTUPINFOEX);
// Get the size of the thread attribute list.
InitializeProcThreadAttributeList(NULL, 1, 0, &attrListSize);
// Allocate a thread attribute list of the correct size
pStartupInfo->lpAttributeList =
reinterpret_cast<LPPROC_THREAD_ATTRIBUTE_LIST>(malloc(attrListSize));
// Initialize thread attribute list
if (pStartupInfo->lpAttributeList
&& InitializeProcThreadAttributeList(pStartupInfo->lpAttributeList, 1, 0, &attrListSize))
{
// Set Pseudo Console attribute
hr = UpdateProcThreadAttribute(
pStartupInfo->lpAttributeList,
0,
PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE,
hPC,
sizeof(HPCON),
NULL,
NULL)
? S_OK
: HRESULT_FROM_WIN32(GetLastError());
}
else
{
hr = HRESULT_FROM_WIN32(GetLastError());
}
}
return hr;
}
void __cdecl PipeListener(LPVOID pipe)
{
HANDLE hPipe{ pipe };
HANDLE hConsole{ GetStdHandle(STD_OUTPUT_HANDLE) };
const DWORD BUFF_SIZE{ 512 };
char szBuffer[BUFF_SIZE]{};
DWORD dwBytesWritten{};
DWORD dwBytesRead{};
BOOL fRead{ FALSE };
do
{
// Read from the pipe
fRead = ReadFile(hPipe, szBuffer, BUFF_SIZE, &dwBytesRead, NULL);
// Write received text to the Console
// Note: Write to the Console using WriteFile(hConsole...), not printf()/puts() to
// prevent partially-read VT sequences from corrupting output
WriteFile(hConsole, szBuffer, dwBytesRead, &dwBytesWritten, NULL);
} while (fRead && dwBytesRead >= 0);
}
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: Ctrl+C is sometimes ignored on Windows Terminal
2021-11-01 8:33 Ctrl+C is sometimes ignored on Windows Terminal Naoto Aoki
@ 2021-11-01 8:50 ` Russell VT
2021-11-01 14:07 ` Doug Henderson
2021-11-02 3:34 ` Takashi Yano
2 siblings, 0 replies; 4+ messages in thread
From: Russell VT @ 2021-11-01 8:50 UTC (permalink / raw)
To: Naoto Aoki; +Cc: cygwin
If you're running things from under Windows Terminal, rather than the
Cygwin terminal, the behavior is likely going to be inconsistent or
unpredictable (and things like interrupts may be handled at a lower level
within the terminal, first, before passing to a higher level and received
by Cygwin).
I'd work on trying to reproduce this in any of the terminals provided by
Cygwin... otherwise, chances are you might need to dig deeper in
MSTerminal, or even WIndows, first.
Regards,
Russell VT
On Mon, Nov 1, 2021 at 1:34 AM Naoto Aoki via Cygwin <cygwin@cygwin.com>
wrote:
> Hi,
>
> When I'm using some programs such as bash and python from cygwin under
> Windows Terminal, Ctrl+C is sometimes ignored.
> https://github.com/microsoft/terminal
>
> Normally holding 'Ctrl' and pressing 'C' will make new line.
> But, sometimes it does not and unholding 'Ctrl' makes new line under
> Windows Terminal.
> bash from msys2 does also reproduce this issue.
>
> I dug into this issue and found that this is related to
> readline and Windows 10's pseudo console (ConPTY).
> I made simple programs to reproduce this issue.
>
> - EchoCon.cpp
> - modification of ConPty sample code provided by Microsoft.
> This program execute bash on pseudo console.
> to be compiled with MSVC.
> - getkey.cpp
> - simple program to check Ctrl+C is passed to Cygwin program.
> to be compiled with Cygwin gcc.
> - rltest.cpp
> - simple program to check SIGINT handling.
> This program reproduces the issue.
> If you replace readline("> ") with gets(buf),
> then the issue does not happen.
> to be compiled with Cygwin gcc.
>
> - The machine and OS that it is running on
> - OS: Windows 10 Pro 19043.1288
> - Windows Terminal: 1.11.2921.0
>
> Regards,
> Naoto Aoki
>
> --
> Problem reports: https://cygwin.com/problems.html
> FAQ: https://cygwin.com/faq/
> Documentation: https://cygwin.com/docs.html
> Unsubscribe info: https://cygwin.com/ml/#unsubscribe-simple
>
--
Russell M. Van Tassell <russellvt@gmail.com>
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: Ctrl+C is sometimes ignored on Windows Terminal
2021-11-01 8:33 Ctrl+C is sometimes ignored on Windows Terminal Naoto Aoki
2021-11-01 8:50 ` Russell VT
@ 2021-11-01 14:07 ` Doug Henderson
2021-11-02 3:34 ` Takashi Yano
2 siblings, 0 replies; 4+ messages in thread
From: Doug Henderson @ 2021-11-01 14:07 UTC (permalink / raw)
To: cygwin
On Mon, 1 Nov 2021 at 02:35, Naoto Aoki via Cygwin <cygwin@cygwin.com> wrote:
>
> Hi,
>
> When I'm using some programs such as bash and python from cygwin under
> Windows Terminal, Ctrl+C is sometimes ignored.
> https://github.com/microsoft/terminal
>
snip
What do you expect to happen when you press Ctrl+C.
- break action aka keyboard interrupt?
- copy selection to clipboard?
Do you expect different behavior determined by whether you have some
text selected?
Is your cygwin installation fully updated via the cygwin setup.exe app?
You should specify the WT version, e.g. Version: 1.11.2921.0. By
default WT updates automatically.
Also, what is in the Action tab of WT Settings, and the Actions
section of the JSON settings at
"%LOCALAPPDATA%\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json"
Also note that https://aka.ms/terminal-profiles-schema is imported at
the top of the settings file, so ...
IIRC, there is also a system wide settings file that is read before
your personal settings file, but I forget where it is. Or maybe there
are some builtin settings, eg Ctrl+Shift+C
HTH
Doug
--
Doug Henderson, Calgary, Alberta, Canada - from gmail.com
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: Ctrl+C is sometimes ignored on Windows Terminal
2021-11-01 8:33 Ctrl+C is sometimes ignored on Windows Terminal Naoto Aoki
2021-11-01 8:50 ` Russell VT
2021-11-01 14:07 ` Doug Henderson
@ 2021-11-02 3:34 ` Takashi Yano
2 siblings, 0 replies; 4+ messages in thread
From: Takashi Yano @ 2021-11-02 3:34 UTC (permalink / raw)
To: cygwin; +Cc: Naoto Aoki
On Mon, 1 Nov 2021 17:33:02 +0900
Naoto Aoki wrote:
> When I'm using some programs such as bash and python from cygwin under
> Windows Terminal, Ctrl+C is sometimes ignored.
> https://github.com/microsoft/terminal
>
> Normally holding 'Ctrl' and pressing 'C' will make new line.
> But, sometimes it does not and unholding 'Ctrl' makes new line under
> Windows Terminal.
> bash from msys2 does also reproduce this issue.
>
> I dug into this issue and found that this is related to
> readline and Windows 10's pseudo console (ConPTY).
> I made simple programs to reproduce this issue.
Thanks for the report.
I could reproduce your problem and identified the cause.
I will submit a patch to fix this issue shortly.
--
Takashi Yano <takashi.yano@nifty.ne.jp>
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2021-11-02 3:35 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-11-01 8:33 Ctrl+C is sometimes ignored on Windows Terminal Naoto Aoki
2021-11-01 8:50 ` Russell VT
2021-11-01 14:07 ` Doug Henderson
2021-11-02 3:34 ` Takashi Yano
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).