tools/qvm-run: handle Ctrl+C nicely
Do not exit with ugly python backtrace, simply interrupt the command (propagate SIGINT) and exit. QubesOS/qubes-issues#4532
This commit is contained in:
parent
9acce13a35
commit
32cbc59ba9
@ -19,7 +19,9 @@
|
|||||||
# with this program; if not, see <http://www.gnu.org/licenses/>.
|
# with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
''' qvm-run tool'''
|
''' qvm-run tool'''
|
||||||
|
import contextlib
|
||||||
import os
|
import os
|
||||||
|
import signal
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
@ -114,13 +116,16 @@ def copy_stdin(stream):
|
|||||||
# multiprocessing.Process have sys.stdin connected to /dev/null, use fd 0
|
# multiprocessing.Process have sys.stdin connected to /dev/null, use fd 0
|
||||||
# directly
|
# directly
|
||||||
while True:
|
while True:
|
||||||
# select so this code works even if fd 0 is non-blocking
|
try:
|
||||||
select.select([0], [], [])
|
# select so this code works even if fd 0 is non-blocking
|
||||||
data = os.read(0, 65536)
|
select.select([0], [], [])
|
||||||
if data is None or data == b'':
|
data = os.read(0, 65536)
|
||||||
|
if data is None or data == b'':
|
||||||
|
break
|
||||||
|
stream.write(data)
|
||||||
|
stream.flush()
|
||||||
|
except KeyboardInterrupt:
|
||||||
break
|
break
|
||||||
stream.write(data)
|
|
||||||
stream.flush()
|
|
||||||
stream.close()
|
stream.close()
|
||||||
|
|
||||||
def main(args=None, app=None):
|
def main(args=None, app=None):
|
||||||
@ -205,7 +210,12 @@ def main(args=None, app=None):
|
|||||||
if args.gui and not args.dispvm:
|
if args.gui and not args.dispvm:
|
||||||
wait_session = vm.run_service('qubes.WaitForSession',
|
wait_session = vm.run_service('qubes.WaitForSession',
|
||||||
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||||
wait_session.communicate(vm.default_user.encode())
|
try:
|
||||||
|
wait_session.communicate(vm.default_user.encode())
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
with contextlib.suppress(ProcessLookupError):
|
||||||
|
wait_session.send_signal(signal.SIGINT)
|
||||||
|
break
|
||||||
if args.service:
|
if args.service:
|
||||||
service = args.cmd
|
service = args.cmd
|
||||||
else:
|
else:
|
||||||
@ -239,8 +249,15 @@ def main(args=None, app=None):
|
|||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
vm.log.error(str(e))
|
vm.log.error(str(e))
|
||||||
return -1
|
return -1
|
||||||
for proc in procs:
|
try:
|
||||||
retcode = max(retcode, proc.wait())
|
for proc in procs:
|
||||||
|
retcode = max(retcode, proc.wait())
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
for proc in procs:
|
||||||
|
with contextlib.suppress(ProcessLookupError):
|
||||||
|
proc.send_signal(signal.SIGINT)
|
||||||
|
for proc in procs:
|
||||||
|
retcode = max(retcode, proc.wait())
|
||||||
finally:
|
finally:
|
||||||
if dispvm:
|
if dispvm:
|
||||||
dispvm.cleanup()
|
dispvm.cleanup()
|
||||||
|
Loading…
Reference in New Issue
Block a user