tktk
tktk

Reputation: 11734

Daemon thread launching software won't die

I'm trying to write a small script which will use plink.exe (from the same folder) to create a ssh tunnel (on windows). I'm basically using os.system to launch the the command:

import time
import threading
from os.path import join, dirname, realpath
pc_tunnel_command = '-ssh -batch -pw xxxx -N -L 1234:host1:5678 user@host2'

if __name__ == '__main__':
    t = threading.Thread(target = os.system, \
                         args = (join(dirname(realpath(__file__)), 'plink.exe ') + \
                                      pc_tunnel_command,))
    t.daemon = True
    t.start()
    #without this line it will die. I guess that plink doesn't have enough time to start.
    time.sleep(5) 
    print 'Should die now'

However, it seems that the thread (and plink.exe) keep running. Why is this happening? Any way to force the thread to close? Better way to launch plink?

I want plink.exe to die when my program ends. Using a daemon thread was my plan of having the tunnel run in the background, and then dying when my main code exits.

BTW - same thing happens with subprocess.call.

Upvotes: 1

Views: 354

Answers (2)

dano
dano

Reputation: 94881

You can use the atexit and signal modules to register calls back that will explicitly kill the process when your program exits normally or receives SIGTERM, respectively:

import sys
import time
import atexit
import signal
import subprocess
from functools import partial
from os.path import join, dirname, realpath

pc_tunnel_command = '-ssh -batch -pw xxxx -N -L 1234:host1:5678 user@host2'


def handle_exit(p, *args):
    print("killing it")
    p.terminate()
    sys.exit(0)

if __name__ == '__main__':
    p = subprocess.Popen(join(dirname(realpath(__file__)), 'plink.exe ') + pc_tunnel_command, shell=True)
    func = partial(handle_exit, p)
    signal.signal(signal.SIGTERM, func)
    atexit.register(func)
    print 'Should die now'

The one thing that is odd about the behavior your desrcibed is that I would have expected your program to exit after your sleep call, but leave plink running in the background, rather than having your program hang until the os.system call completes. That's the behavior I see on Linux, at least. In any case, explicitly terminating the child process should solve the issue for you.

Upvotes: 1

flodin
flodin

Reputation: 5244

os.system does not return until the child process exits. The same is true for subprocess.call. That's why your thread is sitting there, waiting for plink to finish. You can probably use subprocess.Popen to launch the process asynchronously and then exit. In any case, the additional thread you are creating is unnecessary.

Upvotes: 0

Related Questions