TCL Commad quit_flatcam doesn't exit when used with --shellfile

Issue #360 resolved
Oliver created an issue

Hello,

the TCL command “quit_flatcam” doesn’t exit the FlatCAM program when used in a script using the parameter.

This can be tested by running a simple script file with only this single command in one line.

The command is working fine when a) entering the command in the TCL command line or b) running the script file from the GUI using “File->Scripting->Run Script…”. In both cases, the application terminates.

When running with the same script file using --shellfile, the application keeps running and must be terminated manually (e.g. with “File->Exit”).

Tested on Ubuntu 18.04.3 64 bit using the following command:

/usr/bin/python3 /path/to/FlatCAM_beta_8.991/FlatCAM.py --shellfile=/path/to/quit.FlatScript

Content of /path/to/quit.FlatScript

quit_flatcam

Affected versions:

Beta 8.991 (also: 8.99, 8.98, 8.97)

Thanks + regards
Oliver

Comments (14)

  1. Marius Stanciu

    Hi Oliver,
    In the file:
    FlatCAM_folder\config\configuration.txt

    what is the value for the ‘headless’ parameter?

    LE: Actually it should not matter. I just tested it in Windows and it works as expected. It may be something specific to Linux but since I don’t develop under Linux … it may take a little time to solve this until I manage to make a virtual machine with Linux.
    BTW, try to use the PyQt=5.12.0. Anything greater than this creates issues in Windows and in OSX. May create issues in Linux, too.

  2. Oliver reporter

    Hi Marius,

    I'm am running the 8.991 from your download folder (FlatCAM_beta_8.991_sources.zip) without any modifications.
    The headless parameter is set to False in the config file:

    FlatCAM_beta_8.991/config/configuration.txt:

    portable=False
    headless=False
    

    I have temporarily modified the file:
    a) changed the setting to True,
    b) removed the parameter from the file.

    Both changes had no effect. The GUI is still starting up and I need to exit manually.

    I also tried starting with the --headless=1 option on the command line. This has the effect the the GUI is not shown, bit the applicazion still doesn't terminate. Without GUI I can only terminate the program from another shell session using the Linux kill command.

    Here is the terminal output when running with "--headless=1":

    [DEBUG] Initialization of the FlatCAM Geometry Editor is finished ...
    [DEBUG][MainThread] Initialization of the FlatCAM Excellon Editor is finished ...
    [DEBUG][MainThread] Initialization of the FlatCAM Gerber Editor is finished ...
    [DEBUG][MainThread] Finished adding FlatCAM Editor's.
    [DEBUG][MainThread] END of constructor. Releasing control.
    [WARNING][MainThread] *******************  RUNNING HEADLESS  *******************
    WARNING: QWidget::setMaximumSize: (/_ExpandableTextEdit) Negative sizes (16777215,-1) are not possible
    [DEBUG][MainThread] TCL command '<class 'tclCommands.TclCommandQuit.TclCommandQuit'>' executed.
    [DEBUG][MainThread] App.final_save() --> App Defaults saved.
    [DEBUG][MainThread] App.final_save() --> App UI state saved.
    WARNING: QWidget::setMaximumSize: (/_ExpandableTextEdit) Negative sizes (16777215,-28) are not possible
    

    (The only difference compared to running with the GUI are the QWidget warningsa and the "RUNNING HEADLESS" message).

    My PyQt version here is 5.10.1. Not sure if I can easily switch to 5.12.0.

    kind regards
    Oliver

  3. Marius Stanciu

    I guess your PyQt version should be fine since it’s not over 5.12.0.

    The actual quit command is a PyQt command: QtWidgets.qApp.quit() which is supposed to kill the app instantly.
    Reading this: https://stackoverflow.com/questions/38283705/proper-way-to-quit-exit-a-pyqt-program I see that it will only kill the event loop which in Windows works fine to kill the app too.
    Can you try the latest commit in the Beta branch? I’ve added there an extra command (it creates some exceptions in Windows), sys.exit() to force exiting from the event loop?

    Please report here if it worked for you or any output it might give if an error is produced.

  4. Oliver reporter

    Hi Marius,

    I have checked the latest commit (134697b3a510) containing your change.
    Unfortunately, it doesn't work. The application still stays open and I need to exit manually.

    Here is the console output:

    [DEBUG][MainThread] TCL command '<class 'tclCommands.TclCommandQuit.TclCommandQuit'>' executed.
    [DEBUG][MainThread] App.final_save() --> App Defaults saved.
    [DEBUG][MainThread] App.final_save() --> App UI state saved.
    [ERROR][MainThread] Exec command Exception: 
        while executing
    "quit_flatcam"
    

    To dig deeper in what's happening I have added a few more debug messages.

    1. In "def exec_command_test():"
            except tk.TclError as e:
                log.debug("OZ: in exec_command_test 'except tk.TclError', type %s" % type(e).__name__)
                # This will display more precise answer if something in TCL shell fails
                result = self.tcl.eval("set errorInfo")
                self.log.error("Exec command Exception: %s" % (result + '\n'))
    

    2. In “def quit_application()":

            log.debug("App.final_save() --> App UI state saved.")
    
            log.debug("OZ: before QtWidgets.qApp.quit()")
            QtWidgets.qApp.quit()
            log.debug("OZ: after QtWidgets.qApp.quit()")
    
            if sys.platform != 'win32':
                log.debug("OZ: before sys.exit()")
                sys.exit()
                log.debug("OZ: after sys.exit()")
    

    Here is the output:

    [DEBUG][MainThread] TCL command '<class 'tclCommands.TclCommandQuit.TclCommandQuit'>' executed.
    [DEBUG][MainThread] App.final_save() --> App Defaults saved.
    [DEBUG][MainThread] App.final_save() --> App UI state saved.
    [DEBUG][MainThread] OZ: before QtWidgets.qApp.quit()
    [DEBUG][MainThread] OZ: after QtWidgets.qApp.quit()
    [DEBUG][MainThread] OZ: before sys.exit()
    [DEBUG][MainThread] OZ: in exec_command_test 'except tk.TclError', type TclError
    [ERROR][MainThread] Exec command Exception: 
        while executing
    "quit_flatcam"
    

    So, it looks like that:

    1. QtWidgets.qApp.quit() doesn't work
    2. sys.exit() is generating a TclError exception which is caught in your error handler.

    Interesting fact:
    When entering the command "quit_flatcam" in the TCL command line, the console output is exactly the same.
    Only that the application terminates in this case.

    Btw.: A quick and dirty solution is to call 'os._exit(0)' rather than 'sys.exit()'.
    (I don't want to recommended this, a cleaner solution may deal with the TCL exception handlers. There must be a reason, why it works as expected when run from the GUI, but not when --shellscript is used.)

    kind regards
    Oliver

  5. Marius Stanciu

    In the latest commit I replaced the QtWidgets.qApp.quit() - which assume a GUI application - with QtCore.QCoreApplication.quit() which in Windows works the same (although it is made for Console apps). May make the difference. Could you try it?

  6. Oliver reporter

    Hi Marius

    I have tried with commit 79a38993ee72. No change.

    When adding my debug messages, I see that it is again running into the exception handler in exec_command_test().

    The exception raised by sys.exit() is of type SystemExit (not Exception, both derive from BaseException). Catching it (and ignoring with pass) doesn’t solve the problem.

    kind regards
    Oliver

  7. Marius Stanciu

    Oops, forgot about the thread I’ve setup to watch for additional launches of the app. It was done for Windows only as initially I used it for recognizing the app being launched by double clicking on a file with the extension associated to FlatCAM (windows - only feature) but later I used it also for this quit_flatcam Tcl command. Fixed.

  8. Oliver reporter

    Hi Marius,

    I have checked the latest commit 1fa69e871440.

    The difference is that the message “Exec command Exception while executing “quit_flatcam”” has gone.
    Otherwise: The application is still not closed, I need to exit manually.

    Here are the debug messages on the console:

    ...
    [DEBUG][MainThread] Initialization of the FlatCAM Excellon Editor is finished ...
    [DEBUG][MainThread] Initialization of the FlatCAM Gerber Editor is finished ...
    [DEBUG][MainThread] Finished adding FlatCAM Editor's.
    [DEBUG][MainThread] END of constructor. Releasing control.
    [DEBUG][MainThread] TCL command '<class 'tclCommands.TclCommandQuit.TclCommandQuit'>' executed.
    [DEBUG][MainThread] App.final_save() --> App Defaults saved.
    [DEBUG][MainThread] App.final_save() --> App UI state saved.
    

    I have also upgraded to PyQt 5.12.0 (using “pip3 install PyQt=5.12.0” - PYQT_VERSION_STR says: “5.12”).

    Upgrading from PyQt 5.10.1 to PyQt 5.12 also doesn't make any differennce.

    Thanks + regards
    Oliver

  9. Marius Stanciu

    Hi Oliver,

    I have tested this fix in a Xubuntu vmware virtual machine and the application is properly closed when passing a script containing the quit_flatcam command. If another instance of the app it’s running, then that instance is closed too.

    Best regards,

    Marius.

  10. Marius Stanciu
    • fixed bug in NCC Tool: after trying to add a tool already in the Tool Table when trying to change the Tool Type the GUI does not change
    • final fix for app not quiting when running a script as argument, script that has the quit_flatcam Tcl command; fixed issue #360
    • fixed issue #363. The Tcl command drillcncjob does not create tool cut, does not allow creation of gcode, it forces the usage of dwell and dwelltime parameters

    → <<cset 3475ae00cd11>>

  11. Oliver reporter

    Hi Marius,

    I have checked today’s latest commit b4076b1e123e from the Beta branch.

    ✅ It’s working now.

    Thank you very much for your effort!

    regards
    Oliver

  12. Log in to comment