microsoft / WSL

Issues found on WSL
https://docs.microsoft.com/windows/wsl
MIT License
17.54k stars 823 forks source link

Ctrl-C terminates WSL console #7959

Open raymod2 opened 2 years ago

raymod2 commented 2 years ago

Version

Microsoft Windows [Version 10.0.19044.1288]

WSL Version

Kernel Version

Linux version 4.4.0-19041-Microsoft

Distro Version

Ubuntu 20.04

Other Software

Python 3.8.0 MinGW 8.1.0

Repro Steps

After executing a build script the WSL console gets into a broken state such that Ctrl-C is not handled properly (it causes the WSL console to close). The build script is written in Python. It invokes a few subprocesses and one of them executes mingw32-make.exe in parallel mode (-O -j16). The Makefile executes two recipes that each call xcopy.exe. This issue is sensitive to small changes. For example, using 'copy' instead of 'xcopy' suppresses the problem.

Process Monitor indicates that both ubuntu2004.exe and wsl.exe exit with code 0xC000013A (STATUS_CONTROL_C_EXIT).

Expected Behavior

Pressing Ctrl-C causes ^C to appear in the bash shell and a new prompt is issued.

Actual Behavior

Pressing Ctrl-C causes the WSL console to terminate (window closes).

Diagnostic Logs

No response

eqn-group commented 2 years ago

Not enough information is provided, kindly attach screenshots. Also use "windows terminal" and go to settings -> Actions -> check close pane and copy text key bindings. otherwise, either configure different keyboard shortcuts in your terminal emulator, use a different terminal emulator.

eqn-group commented 2 years ago

Install windows terminal from microsoft store, then you can launch your distro by typing wsl or if you have multiple distro wsl -d distroname , you can get distro list in cmd by wsl --list .

then open cmd/powershell, click on its icon present on top-left of the titlebar, open properties and uncheck legacy mode.

raymod2 commented 2 years ago

Thank you for the information about Windows Terminal. Since the bug is somewhat elusive I would prefer not to introduce variables that might mask the problem. Instead I'll share the script that I have used to reliably reproduce the issue. It comprises 3 files (build.py, helper.py, and Makefile). You need to launch wsl.exe from the GUI (so it connects to its own console) and execute build.py. Then press Ctrl-C and your console window will close.

build.py:

#!/usr/bin/python3 -u

import errno
import os
import pty
import select
import shlex
import subprocess
import sys

def job_add(jobs, script):
    args      = shlex.split(script)
    dir, file = os.path.split(args.pop(0))  # cross-platform if '/' is used
    dir       = dir if dir else None
    cmd       = [ sys.executable, '-u', file ] + args

    master, slave = pty.openpty()  # these are OS file descriptors (numbers)
    process = subprocess.Popen(cmd, cwd=dir, stdout=slave, stderr=subprocess.STDOUT)
    os.close(slave)  # close parent copy (child copy stays open until child exits)
    jobs[master] = [ process, "", 0 ]  # process, output, error

def job_wait(jobs):
    pending = list(jobs)  # jobs are pending until finished, output flushed, error checked
    running = list(jobs)
    first = pending[0]

    while running:
        ready = select.select(running, [], [])
        for fd in ready[0]:
            try:
                output = os.read(fd, 512).decode()
                if not output: raise OSError(errno.EIO, "")  # is this necessary?
                jobs[fd][1] += output
                if fd == first: print(jobs[first][1], end=""); jobs[first][1] = ""
            except OSError as e:
                if e.errno != errno.EIO: raise
                jobs[fd][2] = jobs[fd][0].wait()  # store error status
                os.close(fd)
                running.remove(fd)
        while first not in running:
            if jobs[first][2]: sys.exit(jobs[first][2])
            pending.remove(first)
            if not pending: break
            first = pending[0]
            print(jobs[first][1], end=""); jobs[first][1] = ""

jobs = {}
job_add(jobs, 'helper.py')
job_wait(jobs)

helper.py:

import shlex
import subprocess
import sys

def mingw_make(args):
    cmd = [ 'mingw32-make.exe' ]
    err = subprocess.call(cmd + shlex.split(args))
    if err: sys.exit(err)

mingw_make('-O -j16')

Makefile;

all : foo bar

foo:
    xcopy /y foo.txt foodir

bar:
    xcopy /y foo.txt foodir
raymod2 commented 2 years ago

image

Here is a screenshot that might be helpful. Here I have reproduced the problem while running my test case from an existing cmd.exe console window. First I run wsl.exe and press Ctrl-C to demonstrate correct handling. Then I run my build script and press Ctrl-C again. This time it drops me back to the cmd.exe shell.

eqn-group commented 2 years ago

Install windows terminal from microsoft store, then you can launch your distro by typing wsl or if you have multiple distro wsl -d distroname , you can get distro list in cmd by wsl --list .

then open cmd/powershell, click on its icon present on top-left of the titlebar, open properties and uncheck legacy mode.

@raymod2 did you read this ? The are known errors with Ubuntu short-cuts icons. I suggest you to run wsl from windows terminal.

I suggest you to uninstall ubuntu, and follow github.com/nckslvrmn/arch_linux_wsl2 to install Arch Linux.

raymod2 commented 2 years ago

@equation-group: Are you being serious? You want me to uninstall Ubuntu and install Arch Linux? That's not helpful. My last screenshot demonstrated this has nothing to do with launching wsl.exe from a shortcut. I also downloaded Windows Terminal and ran my test there and I see the same results. If you really want to help I suggest you grab my test files and try to reproduce this yourself.

raymod2 commented 2 years ago

The build script (build.py) executes an arbitrary number of python scripts in parallel and displays the output of each script in real-time in the order they were launched. In this minimal example there is only one script (helper.py) and it invokes a Makefile that spawns two instances of xcopy.exe.

OneBlue commented 2 years ago

Thanks for reporting this @raymod2.

Can you share the output of strace -f [your command] and whether this issue reproduces with Windows terminal ?

raymod2 commented 2 years ago

image

In the above screenshot I have reproduced the issue in a Windows Terminal. I ran the test using strace and then pressed Ctrl-C after it completed. Is this enough of the trace or do you want me to capture it to a file and share all of it?

ilatypov commented 1 year ago

Also these two lines stall the WSL DOS terminal and/or destroy it on pressing any key. Putting the second line alone into a #! /bin/bash script does the same. They work fine in the (GUI) Windows Terminal.

$ echo a | cat
LANG=en_US.UTF-8 printf '\x80'
>wsl --version
WSL version: 2.0.9.0
Kernel version: 5.15.133.1-1
WSLg version: 1.0.59
MSRDC version: 1.2.4677
Direct3D version: 1.611.1-81528511
DXCore version: 10.0.25131.1002-220531-1700.rs-onecore-base2-hyp
Windows version: 10.0.19043.2364
s-ol commented 1 year ago

I'm also having this issue, but for me it happens in windows terminal even in a completely new session, both in "Ubunbu" tabs and when entering from cmd.exe by running wsl.exe. Whenever I press CTRL-C the wsl process is immediately quit, no matter if I'm currently writing a bash command (which usually would clear the input line), running a command (which should have an opportunity to gracefully quit and drop me back into the shell) or anything else. CTRL-D and CTRL-Z work as expected though.

I've checked the "actions" settings but only "copy text" was bound to CTRL-C, and I've removed that as well to be sure.

I'm currently using this computer via TeamViewer and I feel like I hadn't been having this issue prior, but I can't be sure about that and don't understand how teamviewer could be causing it either.

left: cmd.exe, as you can see ctrl-c while cat is running kills not only cat but also bash and wsl.exe.
right: Ubuntu preset, crl-c kills pane regardless of context image

It seems that wsl.exe should be passing the ctrl-c signal on to the bash process, but isn't?

s-ol commented 1 year ago

I've had a chance to test on the machine in person again, and can confirm that this problem happens only when connected via TeamViewer. I've also found that I can force the behavior I see in that case by pressing ctrl+break on the physical keyboard.

It's however still unclear to me whether this is a bug on TeamViewer's side (which would be somewhat odd because ctrl+c works in other programs), or in the Windows Terminal application, or the way wsl.exe handles signals.

dnso86 commented 10 months ago

(...) this problem happens only when connected via TeamViewer. (...)

Same here.