alexlipa
alexlipa

Reputation: 1271

subprocess.Popen makes terminal crash after KeyboardInterrupt

I wrote a simple python script ./vader-shell which uses subprocess.Popen to launch a spark-shell and I have to deal with KeyboardInterrupt, since otherwise the child process would not die

command = ['/opt/spark/current23/bin/spark-shell']
command.extend(params)

p = subprocess.Popen(command)

try:
  p.communicate()
except KeyboardInterrupt:
  p.terminate() 

This is what I see with ps f

enter image description here

When I actually interrupt with ctrl-C, I see the processes dying (most of the time). However the terminal starts acting weird: I don't see any cursor, and all the lines starts to appear randomly

enter image description here

I am really lost in what is the best way to run a subprocess with this library and how to handle killing of the child processes. What I want to achieve is basic: whenever my python process is killed with a ctrl-C, I want all the family of process being killed. I googled several solutions os.kill, p.wait() after termination, calling subprocess.Popen(['reset']) after termination but none of them worked. Do you know what is the best way to kill when KeyboardInterrupt happens? Or do you know any other more reliable library to use to spin-up processes?

Upvotes: 0

Views: 508

Answers (1)

piwai
piwai

Reputation: 148

There is nothing blatantly wrong with your code, the problem is that the command you are launching tries to do stuff with the current terminal, and does not correctly restore the settings where shutting down. Replacing your command with a "sleep" like below will run just fine and stop on Ctrl+C without problems:

import subprocess

command = ['/bin/bash']
command.extend(['-c', 'sleep 600'])

p = subprocess.Popen(command)

try:
  p.communicate()
except KeyboardInterrupt:
  p.terminate()

I don't know what you're trying to do with spark-shell, but if you don't need it's output you could try to redirect it to /dev/null so that it's doesn't mess up the terminal display:

p = subprocess.Popen(command, stdout=subprocess.DEVNULL)

Upvotes: 1

Related Questions