Python 2 vs Python 3 - Difference in return value of Popen.poll

Viewed 131

Goal

Launch the given command as the child process of a script, wait for it to terminate and also perform the following signal handling when a signal is sent,

When a SIGINT/SIGTERM signal is sent to the script, send it to the sub process and wait for some time to allow the sub process to exit gracefully and then send a SIGKILL if it doesn't exit.

Approach

  1. Launched the command using subprocess.Popen. Wait, poll using Popen.wait and Popen.poll respectively.

  2. Defined a custom signal handler (only for SIGINT for now) which takes care of sending SIGINT to the sub process, waits for a while before polling the sub process and then sends a SIGKILL signal to forcefully terminate the sub process.

Observation

When SIGINT (ctrl+c) is sent to the code snippet added below, the following difference in return value of Popen.poll,

  1. Python 2.7: Poll returns -2 (which indicates that the process was terminated by signal 2)
  2. Python 3.7: Poll returns None (which indicates that the process is still running)

Code

from __future__ import print_function

import time
import signal
from subprocess import Popen
from functools import partial


def handle_signal(command, signal, frame):
    print("Sending signal %d to the command" % signal)
    command.send_signal(signal)
    
    # Wait for some time to allow the command to terminate gracefully
    SLEEP_TIME = 3
    print("Sleeping for %d seconds" % SLEEP_TIME) 
    time.sleep(SLEEP_TIME)
    
    print("Return value of poll: " + str(command.poll()))
    # Here send SIGKILL if poll returns None
    

command = Popen(["sleep", "300"])
signal.signal(signal.SIGINT, partial(handle_signal, command))

print("Launched the command, send a SIGINT")
command.wait()

Questions

  1. Is this difference in behavior expected? If yes, then can anyone point me to the relevant documentation? (I've gone through the documentation for wait and poll in Python 2, 3 but couldn't find what might be causing this)

  2. What is the correct way to achieve the goal described above? (ideally the code should work for both Python 2.7, 3.7 and use the subprocess module)

0 Answers
Related