Closing all threads when Tkinter window is closed

The Problem: Need the program to close completely when the Tkinter window is closed (click in X)

When closing the Tkinter window before the paramiko SSH connection gets stablished the program ends.

1- IF Paramiko connection gets established, closing the Tkinter window wont close the program. But entering anything and pressing enter will close the program.

It seems like the paramiko thread never ends.

How can I close the paramik function thread after a connection is stablished??? What am I doing wrong???

from tkinter import *
from tkinter import ttk
from tkinter.messagebox import showinfo
from PIL import Image, ImageTk
from tkinter import messagebox

#Paramiko Imports
from paramiko import client
from paramiko.py3compat import input
import concurrent.futures # uses the tHread pool executor 
import paramiko
from paramiko.py3compat import u
import threading, sys, traceback

#flag variable
ON = 1
# GUI Function 
def gui():
    global root
    root = Tk() 
    root.title(" MY Gui") 
    root.geometry("1050x590") 
    # Create the canvas
    my_canvas = Canvas(root, width=1050, height=590)
    my_canvas.pack()

    root.protocol("WM_DELETE_WINDOW", on_closing_main)
    root.mainloop()

def on_closing_main():
    if messagebox.askokcancel("Quit", "Do you want to close the main window?"):
        global ON
        ON = 0
        root.destroy()


def paramik():
    # needed parameters for connection    
    port = 22
    hostname = 'beaglebone'
    username = 'debian'
    password = 'pass'
   
    global chan
    client = paramiko.SSHClient()
    client.load_system_host_keys()
    client.set_missing_host_key_policy(paramiko.WarningPolicy())
    print("*** Connecting...")
    client.connect(hostname, port, username, password)

    chan = client.invoke_shell()
    print(repr(client.get_transport()))
    chan.send('python3 a.py\n')
    print("*** SSH Connection to BB_AI stablished!\n")

    ##########################################################
    def writeall(sock):
        
        while True:
            data = sock.recv(9999).decode('utf8')
            if not data or not ON:
                sys.stdout.write("\r\n*** EOF ***\r\n\r\n")
                sys.stdout.flush()
                chan.close()
                client.close()
                break
         
                
            # write to console
            print(data, end= '\r', flush= True)

        # This exits the program when the Tkinter window is closed as long
        # as the connection doesn't go through in paramiko
        if not ON:
            return 'Exiting'

    writer = threading.Thread(target=writeall, args=(chan,))
    writer.start()

    try:
        while True:
            d = sys.stdin.read(1)
            if not d:
                break
            # If  after  paramiko stablishes a connection the Tkinter window 
            # is closed then the paramik function thread dosnt seem to end so entering 
            # anthing in console will terminate the Program

            # Needed to terminate as soon as the Tkinter window x is clicked!! 
            if not ON:
                return 'Done'
            chan.send(d)
    except EOFError:
        pass

    chan.close()
    client.close()
    

def main():      
    with concurrent.futures.ThreadPoolExecutor() as executor:
        
        t1 = executor.submit(paramik)
        
        print(t1.result(), end= '\r\n', flush=True)
        
        if t1.done():
            executor._threads.clear()
            concurrent.futures.thread._threads_queues.clear()
            sys.exit()
            
              

if __name__ == "__main__" : main() 

Upvotes: 1

Views: 3058

Answers (1)

bookofproofs
bookofproofs

Reputation: 354

Instead of while True: in def writeall(sock): you could use an internal bool variable, for instance while not self._stop:. Then, write in def gui(): simply

self._stop = False
root.mainloop()
self._stop = True

Upvotes: 2

Related Questions