1

I am building a terminal shell program using tkinter. The user is able to run any arbitrary program (not always python scripts). This is how I start the new process:

self.proc = subprocess.Popen("test.py", close_fds=False, shell=True, **get_std_child())

This is my test.py program:

import time
try:
    print("Start")
    time.sleep(10)
    print("End")
except KeyboardInterrupt as error:
    print(repr(error), "!")

I am having trouble sending a Ctrl-c event to the process. I am using Python 3.7.9. I tried all of these but none of them have the desired effect.

from signal import SIGINT, CTRL_C_EVENT, CTRL_BREAK_EVENT
proc.send_signal(SIGINT) # `ValueError: Unsupported signal: 2`
os.kill(proc.pid, SIGINT) # Doesn't do anything until I press it again then it throws: PermissionError: [WinError 5] Access is denied
os.kill(proc.pid, CTRL_C_EVENT) # SystemError: <built-in function kill> returned a result with an error set
os.kill(proc.pid, CTRL_BREAK_EVENT) # SystemError: <built-in function kill> returned a result with an error set

According to the signal documentation SIGINT as well as CTRL_C_EVENT should work on Windows.

The desired effect is the same as what happens to cmd when I press Ctrl-c:

C:\Users\TheLizzard\Documents\GitHub\Bismuth-184\src>python test.py
Start
KeyboardInterrupt() !

C:\Users\TheLizzard\Documents\GitHub\Bismuth-184\src>

PS: The full code is here but it's very long.

TheLizzard
  • 7,248
  • 2
  • 11
  • 31

1 Answers1

0

If you want to kill test.py using Ctrl + C, then try something like

def signal_handler(signal):
            self.proc.terminate()
            sys.exit(0)
        
signal.signal(signal.SIGINT, signal_handler)

Feel free to comment in case of any question.

Usama Tariq
  • 169
  • 5
  • I want the process to handle the Ctrl-C normally as if I ran the program in cmd. Also I don't control `test.py` and I am running arbitrary `.exe`s with my program. – TheLizzard Mar 27 '21 at 15:04
  • Oh I am sorry, I have never worked with .exe So I have no idea of that. – Usama Tariq Mar 27 '21 at 15:08
  • Is there a way to simulate a Ctrl-C event in a child process using the `subprocess`/`signal` library? – TheLizzard Mar 27 '21 at 15:09
  • I faced the same issue and learned that you cant do anything directly into the file of child process. To handle this problem I created the function in child process file and wrote everything you want to get it react on Ctrl-C and I called that from main file where the subprocess created into the function I shared above. – Usama Tariq Mar 27 '21 at 15:18
  • How does `cmd` handle `Ctrl-C` events? IDLE can also send `KeyboardInterrupt`s. According to [this](https://stackoverflow.com/a/66298508/11106801) *"[IDLE] executes user code in a separate process"*. I think that it's possible but I don't know how to do it. – TheLizzard Mar 27 '21 at 20:20
  • It's interesting, I dont know too. Will look into it. If you come across any answer do share it here – Usama Tariq Mar 27 '21 at 20:37
  • This person changed the behavior of Ctrl-C. Do look into this link [link] https://stackoverflow.com/questions/37378185/handle-ctrl-c-in-python-cmd-module – Usama Tariq Mar 27 '21 at 20:41
  • Someone partially solved this in my other question [here](https://stackoverflow.com/a/66840133/11106801) by using pty pipes instead of tty pipes. The problem how is that the only way to have pty pipes on Windows is by using Window's api (`CreatePipe`) but no libraries support it including `ctypes` and `pywin32`. I filed a bug report [here](https://github.com/mhammond/pywin32/issues/1684) and maybe they will add it so I can finish my terminal :D – TheLizzard Mar 28 '21 at 22:20
  • Don't know if that'll help, but if you want to emulate or do something similar to `CreatePipe`, take a look at this: https://stackoverflow.com/questions/34504970/non-blocking-read-on-os-pipe-on-windows @TheLizzard – Nordine Lotfi Nov 16 '22 at 10:39