Browse Source

Close wxGUI on GRASS CLI exit (https://trac.osgeo.org/grass/ticket/770) - experimental prototype

git-svn-id: https://svn.osgeo.org/grass/grass/trunk@67306 15284696-431f-4ddb-bdfa-cd5b030d7da7
Martin Landa 9 years ago
parent
commit
98e289afa9
3 changed files with 53 additions and 5 deletions
  1. 27 1
      gui/wxpython/core/utils.py
  2. 9 2
      gui/wxpython/wxgui.py
  3. 17 2
      lib/init/grass.py

+ 27 - 1
gui/wxpython/core/utils.py

@@ -3,7 +3,7 @@
 
 @brief Misc utilities for wxGUI
 
-(C) 2007-2013 by the GRASS Development Team
+(C) 2007-2015 by the GRASS Development Team
 
 This program is free software under the GNU General Public License
 (>=v2). Read the file COPYING that comes with GRASS for details.
@@ -1125,6 +1125,32 @@ def doc_test():
     do_doctest_gettext_workaround()
     return doctest.testmod().failed
 
+def registerPid(pid):
+    """Register process id as GUI_PID GRASS variable
 
+    :param: pid process id
+    """
+    env = grass.gisenv()
+    guiPid = []
+    if 'GUI_PID' in env:
+        guiPid = env['GUI_PID'].split(',')
+    guiPid.append(str(pid))
+    grass.run_command('g.gisenv', set='GUI_PID={}'.format(','.join(guiPid)))
+    
+def unregisterPid(pid):
+    """Unregister process id from GUI_PID GRASS variable
+
+    :param: pid process id
+    """
+    env = grass.gisenv()
+    if 'GUI_PID' not in env:
+        return
+    
+    guiPid = env['GUI_PID'].split(',')
+    pid = str(os.getpid())
+    if pid in guiPid:
+        guiPid.remove(pid)
+        grass.run_command('g.gisenv', set='GUI_PID={}'.format(','.join(guiPid)))
+    
 if __name__ == '__main__':
     sys.exit(doc_test())

+ 9 - 2
gui/wxpython/wxgui.py

@@ -20,9 +20,10 @@ This program is free software under the GNU General Public License
 import os
 import sys
 import getopt
+import atexit
 
 from core import globalvar
-from core.utils import _
+from core.utils import _, registerPid, unregisterPid
 
 from grass.exceptions import Usage
 from grass.script.core import set_raise_on_error
@@ -110,7 +111,9 @@ def process_opt(opts, args):
 
     return workspaceFile
 
-
+def cleanup():
+    unregisterPid(os.getpid())
+        
 def main(argv = None):
 
     if argv is None:
@@ -133,7 +136,11 @@ def main(argv = None):
     q = wx.LogNull()
     set_raise_on_error(True)
 
+    # register GUI PID
+    registerPid(os.getpid())
+    
     app.MainLoop()
 
 if __name__ == "__main__":
+    atexit.register(cleanup)
     sys.exit(main())

+ 17 - 2
lib/init/grass.py

@@ -133,7 +133,7 @@ def clean_env(gisrc):
     env_curr = read_gisrc(gisrc)
     env_new = {}
     for k,v in env_curr.items():
-        if k == 'PID' or k.startswith('MONITOR'):
+        if k.endswith('PID') or k.startswith('MONITOR'):
             continue
         env_new[k] = v
 
@@ -1352,6 +1352,19 @@ def start_gui(grass_gui):
         Popen([os.getenv('GRASS_PYTHON'), wxpath("wxgui.py")])
 
 
+def close_gui():
+    """Close GUI if running"""
+    if gpath('etc', 'python') not in sys.path:
+        sys.path.append(gpath('etc', 'python'))
+    from grass.script import core as gcore  # pylint: disable=E0611
+    env = gcore.gisenv()
+    if 'GUI_PID' not in env:
+        return
+    import signal
+    for pid in env['GUI_PID'].split(','):
+        debug("Exiting GUI with pid={}".format(pid))
+        os.kill(int(pid), signal.SIGTERM)
+        
 def clear_screen():
     """Clear terminal"""
     if windows:
@@ -1904,7 +1917,9 @@ def main():
         exit_val = shell_process.wait()
         if exit_val != 0:
             warning(_("Failed to start shell '%s'") % os.getenv('SHELL'))
-        
+
+        # close GUI if running
+        close_gui()
         # here we are at the end of grass session
         clear_screen()
         # TODO: can we just register this atexit?