Skip to content

Commit

Permalink
Updated execute_command_with_timeout()
Browse files Browse the repository at this point in the history
  • Loading branch information
Paul Nilsson committed Aug 29, 2024
1 parent cf781b6 commit 412114a
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 35 deletions.
2 changes: 1 addition & 1 deletion PILOTVERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3.8.1.56
3.8.1.58
51 changes: 17 additions & 34 deletions pilot/util/container.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import os
import subprocess
import logging
import queue
import re
import shlex
import signal
Expand Down Expand Up @@ -401,59 +402,41 @@ def timeout_handler(signum, frame):
return return_code, output.decode()


def execute_command_with_timeout(command, timeout=30):
def execute_command_with_timeout(command, timeout_seconds=30):
"""Executes a command with a timeout.
Args:
command: The command to execute as a list of strings.
timeout: The maximum execution time in seconds.
timeout_seconds: The maximum execution time in seconds.
Returns:
A tuple containing the return code of the command and the output.
"""

result = [None, None] # Store the result (return code, output)
# convert to list if necessary
_command = shlex.split(command) if isinstance(command, str) else command
result_queue = queue.Queue()

def _execute_command():
logger.info(f"executing command: {command}")
process = subprocess.Popen(_command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

def timeout_handler(signum, frame):
logger.warning(f"command timed out after {timeout} seconds.")
process.send_signal(signal.SIGTERM)

signal.signal(signal.SIGALRM, timeout_handler)
signal.alarm(timeout)
logger.debug('setup signal')
process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

try:
output, errors = process.communicate()
output, errors = process.communicate(timeout=timeout_seconds)
return_code = process.returncode
result[0] = return_code
result[1] = output.decode()
result_queue.put((return_code, output.decode()))
except subprocess.TimeoutExpired:
process.kill()
result_queue.put((-1, "Command timed out"))
except KeyboardInterrupt:
logger.warning("Command interrupted.")
process.send_signal(signal.SIGTERM)
result[0] = -1
except Exception as e:
logger.warning(f"An exception occurred while executing the command: {e}")
finally:
logger.debug(f"gdb debug command finished with exit code: {return_code}, output: {result[1]}")
signal.alarm(0) # Disable the alarm to prevent unexpected behavior
process.kill()
result_queue.put((-1, "Command interrupted"))

# Create a thread to execute the command
thread = threading.Thread(target=_execute_command)
thread.start()
logger.debug('thread started')

# Wait for the thread to finish or time out
thread.join(timeout)
logger.debug('thread joined')

if thread.is_alive():
logger.info(f"Command timed out after {timeout} seconds.")
try:
return_code, output = result_queue.get(timeout=timeout_seconds)
except queue.Empty:
thread.join() # Wait for the thread to finish
return_code, output = result_queue.get()

return result[0], result[1]
return return_code, output

0 comments on commit 412114a

Please sign in to comment.