Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Patch for terminating subprocess after timeout #1

Merged
merged 1 commit into from
Aug 10, 2018
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 24 additions & 7 deletions iotedgedev/azurecli.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import sys
import os
import signal
import subprocess
import json

Expand All @@ -22,27 +24,31 @@ def decode(self, val):
return val.decode("utf-8").strip()

def is_posix(self):
self.envvars.is_posix()
return self.envvars.is_posix()

def prepare_az_cli_args(self, args, suppress_output=False):
if suppress_output:
args.extend(["--query", "\"[?n]|[0]\""])

az_args = ["az"]+args
if self.is_posix():
return [" ".join(az_args)]
return az_args

def invoke_az_cli_outproc(self, args, error_message=None, stdout_io=None, stderr_io=None, suppress_output=False, timeout=None):
try:
if timeout:
timeout = int(timeout)

# Consider using functools
if stdout_io or stderr_io:
process = subprocess.Popen(self.prepare_az_cli_args(args, suppress_output), stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=not self.envvars.is_posix())
process = subprocess.Popen(self.prepare_az_cli_args(args, suppress_output),
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
shell=not self.is_posix(),
preexec_fn=os.setsid if self.is_posix() and 'monitor-events' in args else None)
else:
process = subprocess.Popen(self.prepare_az_cli_args(args, suppress_output), shell=not self.envvars.is_posix())

process = subprocess.Popen(self.prepare_az_cli_args(args, suppress_output),
shell=not self.is_posix(),
preexec_fn=os.setsid if self.is_posix() and 'monitor-events' in args else None)

stdout_data, stderr_data = process.communicate(timeout=timeout)

if stderr_data and b"invalid_grant" in stderr_data:
Expand All @@ -67,7 +73,18 @@ def invoke_az_cli_outproc(self, args, error_message=None, stdout_io=None, stderr
if not stdout_io and not stderr_io:
self.output.line()
except subprocess.TimeoutExpired:
process.kill()
try:
# Suppress sys.excepthook errors from things like C extension forced deallocation
_eh = sys.excepthook
sys.excepthook = lambda type, value, traceback: 0
if self.is_posix():
os.killpg(os.getpgid(process.pid), signal.SIGTERM)
else:
os.kill(process.pid, signal.CTRL_C_EVENT)
process.kill()
finally:
sys.excepthook = _eh

if timeout:
self.output.info("Timeout set to {0} seconds, which expired as expected.".format(timeout))
self.output.line()
Expand Down