0

I'm at a loss for what to do about this situation, as I've googled and even been talking with a couple other developers on GitHub about this for about 4 days now. Minimum reproducer code and stack trace are below. Essentially, the problem lies in between the lic_win.destroy() line and the parent_window.destroy() line. As far as I understand tkinter, these lines should execute properly before the new window appears. What am I missing? This works on Windows no problem.

import tkinter as tk, requests as rq, platform, os, sys, time, hashlib, logging, traceback, Vigenere_Helper, zipfile, re, subprocess
import tkinter.ttk as ttk
from tkinter.constants import *
from tkinter import PhotoImage, messagebox
from logging.handlers import RotatingFileHandler
#
import faulthandler
faulthandler.enable()
#
currentdir = os.path.dirname(os.path.realpath(__file__))
parentdir = os.path.dirname(currentdir)
sys.path.append(parentdir)
homedir = os.path.expanduser(f'~{os.getlogin()}')
#
logger = logging.getLogger("tk_main")
logger.setLevel(logging.DEBUG)
handler = RotatingFileHandler(os.path.join(homedir, 'tk_main.log'), maxBytes=100000, backupCount=5)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s\n%(message)s')
handler.setFormatter(formatter)
logger.addHandler(handler)
#
def get_device_uuid():
    if platform.system() == "Linux":
        # linux
        try:
            return subprocess.run('cat /etc/machine-id', shell=True).stdout
        except Exception as e:
            logger.error(str(e))
            logger.error(traceback.format_exc())
    elif platform.system() == "Darwin":
        # OS X
        cmd = """ioreg -ad2 -c IOPlatformExpertDevice | 
  xmllint --xpath '//key[.="IOPlatformUUID"]/following-sibling::*[1]/text()' -
"""
        try:
            return subprocess.run(cmd, shell=True).stdout
        except Exception as e:
            logger.error(str(e))
            logger.error(traceback.format_exc())
    elif platform.system() == "Windows":
        try:
            from wmi import WMI
            return WMI().Win32_ComputerSystemProduct()[0].UUID
        except Exception as e:
            logger.error(str(e))
            logger.error(traceback.format_exc())
#
def ini_gen(license_key):
    with open(os.path.join(homedir, 'tk_main.ini'), 'w') as fhand:
        timestamp = round(time.time(),2)
        fhand.write(f'{timestamp}\n')
        fhand.write(f'{license_key}\n')
        hasher = hashlib.md5()
        if platform.system() == 'Windows':
            with open(os.path.join(homedir, 'Documents', 'tk_main', 'tk_main.exe'), 'rb') as khand:
                buf = khand.read()
                hasher.update(buf)
        elif platform.system() == 'Darwin':
            with open(os.path.join(homedir, 'Documents', 'tk_main', 'tk_main.app'), 'rb') as khand:
                buf = khand.read()
                hasher.update(buf)
        elif platform.system() == 'Linux':
            with open(os.path.join(homedir, 'Documents', 'tk_main', 'tk_main'), 'rb') as khand:
                buf = khand.read()
                hasher.update(buf)
        fhand.write(f'{hasher.hexdigest()}\n')
    package = {}
    package['type'], package['datetime'], package['license_key'], package['hash'], package['UUID'] = 'ini_gen', timestamp, license_key, hasher.hexdigest(), get_device_uuid()
    try:
        rq.post('http://myworkingapi.com', json=package, allow_redirects=False)
    except Exception as e:
        logger.error(str(e))
        logger.error(traceback.format_exc())
    fhand.close()
#
def license_screen(parent_window):
    lic_win = tk.Toplevel(parent_window)
    lic_win.geometry("450x300+413+395")
    lic_win.minsize(72, 15)
    lic_win.maxsize(900, 600)
    lic_win.resizable(1,  1)
    lic_win.title("tk_main Licenser")
    lic_win.configure(background="#d9d9d9")
    def submit_license(license_input):
        cipher = "Removed for security"
        try:
            license_sub = rq.post('http://myworkingapi.com',json={'type':'license_submit', 'license_key':license_input}, allow_redirects=False)
        except Exception as e:
            logger.error(str(e))
            logger.error(traceback.format_exc())
        if "Removed":
            try:
                ini_gen(license_input)
            except Exception as e:
                logger.error(str(e))
                logger.error(traceback.format_exc())
            time.sleep(5)
            try:
                lic_win.destroy()
                parent_window.destroy()
            except Exception as e:
                logger.error(str(e))
                logger.error(traceback.format_exc())
            try:
                main()
            except Exception as e:
                logger.error(str(e))
                logger.error(traceback.format_exc())
        elif "Removed":
            try:
                messagebox.showerror('Licensing Error','This license has already been activated. Please reach out to support at support@devinmgardner.com for any questions or concerns.')
            except Exception as e:
                logger.error(str(e))
                logger.error(traceback.format_exc())
        elif "Removed":
            try:
                messagebox.showerror('Licensing Error','The key you entered is invalid. Please double check for any mistakes, and reach out to support at support@devinmgardner.com with any questions or concerns.')
            except Exception as e:
                logger.error(str(e))
                logger.error(traceback.format_exc())
        elif "Removed":
            try:
                messagebox.showerror('Licensing Error','The key you entered has previously been disabled, and a new key generated. Please reach out to support at support@devinmgardner.com with any questions or concerns.')
            except Exception as e:
                logger.error(str(e))
                logger.error(traceback.format_exc())
    #
    Label1 = tk.Label(lic_win)
    Label1.place(relx=0.267, rely=0.167, height=22, width=189)
    Label1.configure(background="#d9d9d9")
    Label1.configure(foreground="#000000")
    Label1.configure(text='''Enter your license key below''')
    #
    entrybox1 = tk.Entry(lic_win)
    entrybox1.place(relx=0.044, rely=0.467, height=25, relwidth=0.182)
    entrybox1.configure(background="white")
    entrybox1.configure(font="TkFixedFont")
    entrybox1.configure(foreground="#000000")
    entrybox1.configure(insertbackground="black")
    #
    entrybox2 = tk.Entry(lic_win)
    entrybox2.place(relx=0.289, rely=0.467, height=25, relwidth=0.182)
    entrybox2.configure(background="white")
    entrybox2.configure(font="TkFixedFont")
    entrybox2.configure(foreground="#000000")
    entrybox2.configure(insertbackground="black")
    #
    entrybox3 = tk.Entry(lic_win)
    entrybox3.place(relx=0.533, rely=0.467, height=25, relwidth=0.182)
    entrybox3.configure(background="white")
    entrybox3.configure(font="TkFixedFont")
    entrybox3.configure(foreground="#000000")
    entrybox3.configure(insertbackground="black")
    #
    entrybox4 = tk.Entry(lic_win)
    entrybox4.place(relx=0.778, rely=0.467, height=25, relwidth=0.182)
    entrybox4.configure(background="white")
    entrybox4.configure(font="TkFixedFont")
    entrybox4.configure(foreground="#000000")
    entrybox4.configure(insertbackground="black")
    #
    submit_button = tk.Button(lic_win, command = lambda: submit_license(f'{entrybox1.get()}-{entrybox2.get()}-{entrybox3.get()}-{entrybox4.get()}'))
    submit_button.place(relx=0.422, rely=0.7, height=28, width=79)
    submit_button.configure(activebackground="#ececec")
    submit_button.configure(activeforeground="#000000")
    submit_button.configure(background="#d9d9d9")
    submit_button.configure(cursor="fleur")
    submit_button.configure(foreground="#000000")
    submit_button.configure(highlightbackground="#d9d9d9")
    submit_button.configure(highlightcolor="black")
    submit_button.configure(text='''Submit''')
    lic_win.mainloop()

class Toplevel1:
    def __init__(self, top=None):
        '''This class configures and populates the toplevel window.
           top is the toplevel containing window.'''
        _bgcolor = '#d9d9d9'  # X11 color: 'gray85'
        _fgcolor = '#000000'  # X11 color: 'black'
        _compcolor = '#d9d9d9' # X11 color: 'gray85'
        _ana1color = '#d9d9d9' # X11 color: 'gray85'
        _ana2color = '#ececec' # Closest X11 color: 'gray92'
        #
        top.geometry("600x600+195+172")
        top.minsize(1, 1)
        top.maxsize(3840, 2160)
        top.resizable(1,  1)
        top.title("tk_main")
        #
        self.top = top
        #
        self.Labelframe1 = tk.LabelFrame(self.top)
        self.Labelframe1.place(relx=0.067, rely=0.050, relheight=0.700
                , relwidth=0.867)
        self.Labelframe1.configure(relief='groove')
        self.Labelframe1.configure(text='''Label''')
        #
        self.outputFrame = tk.LabelFrame(self.top)
        self.outputFrame.place(relx=0.067, rely=0.750, relheight=0.200
                , relwidth=0.867)
        #
        self.scrollbar = tk.Scrollbar(self.outputFrame)
        self.scrollbar.pack(side = 'right',fill='y')
        self.outputwindow = tk.Text(self.outputFrame, yscrollcommand = self.scrollbar.set,wrap = "word",width = 200,font = "{Arial} 15")
        self.outputwindow.pack(side = 'left',fill='y')
        self.scrollbar.config(command = self.outputwindow.yview)
        self.outputwindow.yview('end')
        self.outputwindow.config(yscrollcommand=self.scrollbar.set)
        self.outputwindow.insert('end','Error messages will appear here.\n')
        self.outputwindow.config(state='disabled')
        self.outputwindow.see('end')
        #
        self.new_List = tk.Listbox(self.Labelframe1)
        self.new_List.place(relx=0.038, rely=0.109, relheight=0.750
                , relwidth=0.450, bordermode='ignore')
        self.new_List.configure(background="white")
        self.new_List.configure(font="TkFixedFont")
        self.new_List.configure(selectmode='multiple')
        #
        def choose():
            listsize = self.new_List.size()
            self.new_List.delete(0,listsize-1)
            activelist = []
            global location
            location = choose_file()
            global displaylist
            displaylist = []
            displaylist = list_new_files(location)
            global displaydict
            displaydict = {}
            try:
                for locat,val in enumerate(displaylist):
                    newval = re.search('\/([^\/]*\..*)',val).group(1)
                    displaydict[newval] = val
                    self.new_List.insert(locat, newval)
            except Exception as e:
                logger.error(str(e))
                logger.error(traceback.format_exc())
        #
        self.new_Canvas = tk.Label(self.Labelframe1)
        self.new_Canvas.place(relx=0.538, rely=0.109, relheight=0.750
                , relwidth=0.450, bordermode='ignore')
        self.new_Canvas.configure(text='Font examples will appear here.')
        #
        self.browseButton = tk.Button(self.Labelframe1)
        self.browseButton.place(relx=0.3653846, rely=0.875, height=33, width=140, anchor='nw')
        self.browseButton.configure(borderwidth="2")
        self.browseButton.configure(compound='left')
        self.browseButton.configure(text='''Choose a different ZIP file''')
        self.browseButton.configure(command=choose)
        #
        def endprog():
            sys.exit()
        #
        self.exitButton = tk.Button(self.Labelframe1)
        self.exitButton.place(relx=0.6826923, rely=0.875, height=33, width=140, anchor='nw')
        self.exitButton.configure(borderwidth="2")
        self.exitButton.configure(compound='left')
        self.exitButton.configure(text='''Exit''')
        self.exitButton.configure(command=endprog)
        #
        choose()
        #


def choose_file():
    from tkinter import Tk, filedialog
    root = Tk()
    root.withdraw()
    root.attributes('-topmost', True)
    try:
        open_file = filedialog.askopenfilename()
    except Exception as e:
        logger.error(str(e))
        logger.error(traceback.format_exc())
    global filelist
    try:
        filelist = zipfile.ZipFile(open_file,mode='r')
    except Exception as e:
        logger.error(str(e))
        logger.error(traceback.format_exc())
    try:
        data = filelist.namelist()
    except Exception as e:
        logger.error(str(e))
        logger.error(traceback.format_exc())
    try:
        return data
    except Exception as e:
        logger.error(str(e))
        logger.error(traceback.format_exc())
#
def list_new_files(openfile):
    files = [a for a in openfile if '.ttf' in a]
    return files

def main(*args):
    '''Main entry point for the application.'''
    global root
    root = tk.Tk()
    root.protocol( 'WM_DELETE_WINDOW' , root.destroy)
    # Creates a toplevel widget.
    global _top1, _w1
    _top1 = root
    _w1 = Toplevel1(_top1)
    root.mainloop()

if __name__ == '__main__':
    license_window = tk.Tk()
    license_window.withdraw()
    license_screen(license_window)

Stack trace:

Fatal Python error: Segmentation fault

Current thread 0x0000000108f48600 (most recent call first):
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/tkinter/commondialog.py", line 45 in show
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/tkinter/filedialog.py", line 384 in askopenfilename
  File "/Users/devingardner/Desktop/coding/tk_main/binaries/macos/minimum_reproducer/minimum_reproducer.py", line 276 in choose_file
  File "/Users/devingardner/Desktop/coding/tk_main/binaries/macos/minimum_reproducer/minimum_reproducer.py", line 229 in choose
  File "/Users/devingardner/Desktop/coding/tk_main/binaries/macos/minimum_reproducer/minimum_reproducer.py", line 266 in __init__
  File "/Users/devingardner/Desktop/coding/tk_main/binaries/macos/minimum_reproducer/minimum_reproducer.py", line 309 in main
  File "/Users/devingardner/Desktop/coding/tk_main/binaries/macos/minimum_reproducer/minimum_reproducer.py", line 109 in submit_license
  File "/Users/devingardner/Desktop/coding/tk_main/binaries/macos/minimum_reproducer/minimum_reproducer.py", line 166 in <lambda>
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/tkinter/__init__.py", line 1921 in __call__
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/tkinter/__init__.py", line 1458 in mainloop
  File "/Users/devingardner/Desktop/coding/tk_main/binaries/macos/minimum_reproducer/minimum_reproducer.py", line 176 in license_screen
  File "/Users/devingardner/Desktop/coding/tk_main/binaries/macos/minimum_reproducer/minimum_reproducer.py", line 315 in <module>
Segmentation fault: 11
  • Why do you create another `root` window in `choose_file`? You never use it, and you don't destroy it. You do have a confusing multitude of top-level windows and multiple mainloops here. – Tim Roberts Apr 24 '22 at 01:45
  • I believe I originally had that there as there was a blank Tk window being created during the `filedialog` prompt, and that was messing with the image display later in the program. I can confirm, however, that removing it does not get rid of the seg fault. – Devin Gardner Apr 24 '22 at 01:58
  • I see three `Tk()` instances created in your code. You should never have more than one instance of `Tk` in your program. Try using `Toplevel` instead, and just using `Tk` for the main window. – Sylvester Kruin Apr 24 '22 at 21:03
  • If I use `Toplevel()` for everything other than the main program, I get a blank `Tk()` window created during license submission, that then doesn't go away and prevents images from displaying properly in the main application window. – Devin Gardner Apr 24 '22 at 21:17
  • Hmm... that might be because you haven't passed the main `Tk()` window to the `Toplevel`'s `master` argument, and/or because your images were [created in a function](https://stackoverflow.com/q/16424091/16775594). But perhaps you need to rethink the structure of your app, too. – Sylvester Kruin Apr 24 '22 at 21:24
  • That wouldn't be an issue if it wasn't already live for Windows and Linux because it works on both of those platforms flawlessly...so not exactly an option I'd like to take right now. I don't understand why I'm having this problem specifically on macOS. – Devin Gardner Apr 24 '22 at 21:39

0 Answers0