Salome HOME
EDF bug 17743, salome.sg regressions in DEV (missing getAllSelected method)
[modules/kernel.git] / bin / killSalomeWithPort.py
index fe36a1e782eb8fd1ef8d13b91730cab2465bc525..fec9e4aa356850f7a1794f4bc39e881283a9febf 100755 (executable)
@@ -1,6 +1,6 @@
-#! /usr/bin/env python
+#! /usr/bin/env python3
 #  -*- coding: iso-8859-1 -*-
 #  -*- coding: iso-8859-1 -*-
-# Copyright (C) 2007-2014  CEA/DEN, EDF R&D, OPEN CASCADE
+# Copyright (C) 2007-2017  CEA/DEN, EDF R&D, OPEN CASCADE
 #
 # Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
 # CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
 #
 # Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
 # CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
 #  \endcode
 #
 
 #  \endcode
 #
 
-import os, sys, pickle, signal, commands,glob
+import os, sys, pickle, signal, subprocess,glob
+import subprocess
+import shlex
 from salome_utils import verbose
 from salome_utils import verbose
-import salome_utils
 
 
-def getPiDict(port,appname='salome',full=True,hidden=True,hostname=None, with2809pid=False):
+
+def getPiDict(port,appname='salome',full=True,hidden=True,hostname=None):
     """
     Get file with list of SALOME processes.
     This file is located in the user's home directory
     """
     Get file with list of SALOME processes.
     This file is located in the user's home directory
@@ -52,7 +54,14 @@ def getPiDict(port,appname='salome',full=True,hidden=True,hostname=None, with280
     - hidden  : if True, file name is prefixed with . (dot) symbol; this internal parameter is used
     to support compatibility with older versions of SALOME
     """
     - hidden  : if True, file name is prefixed with . (dot) symbol; this internal parameter is used
     to support compatibility with older versions of SALOME
     """
-    from salome_utils import generateFileName, getTmpDir
+    # bug fix: ensure port is an integer
+    # Note: this function is also called with port='#####' !!!
+    try:
+        port = int(port)
+    except:
+        pass
+
+    from salome_utils import generateFileName, getLogDir
     dir = ""
     if not hostname:
         hostname = os.getenv("NSHOST")
     dir = ""
     if not hostname:
         hostname = os.getenv("NSHOST")
@@ -63,7 +72,7 @@ def getPiDict(port,appname='salome',full=True,hidden=True,hostname=None, with280
         if hidden:
             # new-style dot-prefixed pidict files
             # are in the system-dependant temporary diretory
         if hidden:
             # new-style dot-prefixed pidict files
             # are in the system-dependant temporary diretory
-            dir = getTmpDir()
+            dir = getLogDir()
         else:
             # old-style non-dot-prefixed pidict files
             # are in the user's home directory
         else:
             # old-style non-dot-prefixed pidict files
             # are in the user's home directory
@@ -71,11 +80,8 @@ def getPiDict(port,appname='salome',full=True,hidden=True,hostname=None, with280
             pass
         pass
 
             pass
         pass
 
-    suffix = "pidict"
-    if port == 2809 and with2809pid:
-        suffix = suffix + "-%s"%(os.getpid())
     return generateFileName(dir,
     return generateFileName(dir,
-                            suffix=suffix,
+                            suffix="pidict",
                             hidden=hidden,
                             with_username=True,
                             with_hostname=hostname or True,
                             hidden=hidden,
                             with_username=True,
                             with_hostname=hostname or True,
@@ -89,6 +95,9 @@ def appliCleanOmniOrbConfig(port):
     - ${OMNIORB_USER_PATH}/.omniORB_${USER}_last.cfg
     the last is removed only if the link points to the first file.
     """
     - ${OMNIORB_USER_PATH}/.omniORB_${USER}_last.cfg
     the last is removed only if the link points to the first file.
     """
+    if verbose():
+        print("clean OmniOrb config for port %s"%port)
+
     from salome_utils import generateFileName, getUserName
     omniorbUserPath = os.getenv("OMNIORB_USER_PATH")
     if omniorbUserPath is None:
     from salome_utils import generateFileName, getUserName
     omniorbUserPath = os.getenv("OMNIORB_USER_PATH")
     if omniorbUserPath is None:
@@ -157,6 +166,8 @@ def shutdownMyPort(port, cleanup=True):
     - port - port number
     """
     if not port: return
     - port - port number
     """
     if not port: return
+    # bug fix: ensure port is an integer
+    port = int(port)
 
     try:
         from PortManager import releasePort
 
     try:
         from PortManager import releasePort
@@ -186,14 +197,16 @@ def shutdownMyPort(port, cleanup=True):
     try:
         import time
         from omniORB import CORBA
     try:
         import time
         from omniORB import CORBA
+
         from LifeCycleCORBA import LifeCycleCORBA
         # shutdown all
         orb = CORBA.ORB_init([''], CORBA.ORB_ID)
         from LifeCycleCORBA import LifeCycleCORBA
         # shutdown all
         orb = CORBA.ORB_init([''], CORBA.ORB_ID)
-        lcc = LifeCycleCORBA(orb)
+        lcc = LifeCycleCORBA(orb) # see (1)
+        print("Terminating SALOME on port %s..."%(port))
         lcc.shutdownServers()
         # give some time to shutdown to complete
         time.sleep(1)
         lcc.shutdownServers()
         # give some time to shutdown to complete
         time.sleep(1)
-        # shutdown omniNames and notifd
+        # shutdown omniNames
         if cleanup:
             lcc.killOmniNames()
             time.sleep(1)
         if cleanup:
             lcc.killOmniNames()
             time.sleep(1)
@@ -201,87 +214,71 @@ def shutdownMyPort(port, cleanup=True):
         pass
     except:
         pass
         pass
     except:
         pass
+    sys.exit(0) # see (1)
     pass
     pass
+# (1) If --shutdown-servers option is set to 1, session close procedure is
+# called twice: first explicitly by salome command, second by automatic
+# atexit to handle Ctrl-C. During second call, LCC does not exist anymore and
+# a RuntimeError is raised; we explicitly exit this function with code 0 to
+# prevent parent thread from crashing.
 
 def __killMyPort(port, filedict):
 
 def __killMyPort(port, filedict):
-    try:
-        with open(filedict, 'r') as fpid:
-            #
-            from salome_utils import generateFileName
-            if sys.platform == "win32":
-                username = os.getenv( "USERNAME" )
-            else:
-                username = os.getenv('USER')
-            path = os.path.join('/tmp/logs', username)
-            fpidomniNames = generateFileName(path,
-                                             prefix="",
-                                             suffix="Pid_omniNames",
-                                             extension="log",
-                                             with_port=port)
-            if not sys.platform == 'win32':
-                cmd = 'pid=`ps -eo pid,command | egrep "[0-9] omniNames -start %s"` ; echo $pid > %s' % ( str(port), fpidomniNames )
-                a = os.system(cmd)
-                pass
-            try:
-                with open(fpidomniNames) as fpidomniNamesFile:
-                    lines = fpidomniNamesFile.readlines()
+    # bug fix: ensure port is an integer
+    if port:
+        port = int(port)
 
 
-                os.remove(fpidomniNames)
-                for l in lines:
+    try:
+        with open(filedict, 'rb') as fpid:
+            process_ids=pickle.load(fpid)
+            for process_id in process_ids:
+                for pid, cmd in list(process_id.items()):
+                    if verbose(): print("stop process %s : %s"% (pid, cmd[0]))
                     try:
                     try:
-                        pidfield = l.split()[0] # pid should be at the first position
-                        if sys.platform == "win32":
-                            import win32pm
-                            if verbose(): print 'stop process '+pidfield+' : omniNames'
-                            win32pm.killpid(int(pidfield),0)
-                        else:
-                            if verbose(): print 'stop process '+pidfield+' : omniNames'
-                            os.kill(int(pidfield),signal.SIGKILL)
-                            pass
-                        pass
+                        from salome_utils import killpid
+                        killpid(int(pid))
                     except:
                     except:
+                        if verbose(): print("  ------------------ process %s : %s not found"% (pid, cmd[0]))
                         pass
                         pass
-                    pass
-                pass
-            except:
-                pass
-            #
-            try:
-                process_ids=pickle.load(fpid)
-                for process_id in process_ids:
-                    for pid, cmd in process_id.items():
-                        if verbose(): print "stop process %s : %s"% (pid, cmd[0])
-                        try:
-                            if sys.platform == "win32":
-                                import win32pm
-                                win32pm.killpid(int(pid),0)
-                            else:
-                                os.kill(int(pid),signal.SIGKILL)
-                                pass
-                            pass
-                        except:
-                            if verbose(): print "  ------------------ process %s : %s not found"% (pid, cmd[0])
-                            pass
-                        pass # for pid, cmd ...
-                    pass # for process_id ...
-                pass # try...
-            except:
-                pass
-        # end with
-        #
-        os.remove(filedict)
-        cmd='ps -eo pid,command | egrep "[0-9] omniNames -start '+str(port)+'" | sed -e "s%[^0-9]*\([0-9]*\) .*%\\1%g"'
-        pid = commands.getoutput(cmd)
-        a = ""
-        while pid and len(a.split()) < 2:
-            a = commands.getoutput("kill -9 " + pid)
-            pid = commands.getoutput(cmd)
-            pass
-        pass
+                    pass # for pid ...
+                pass # for process_id ...
+            # end with
     except:
     except:
-        print "Cannot find or open SALOME PIDs file for port", port
+        print("Cannot find or open SALOME PIDs file for port", port)
         pass
         pass
-    #
+    os.remove(filedict)
+    pass
+#
+
+def __guessPiDictFilename(port):
+    from salome_utils import getShortHostName, getHostName
+    filedicts = [
+        # new-style dot-prefixed pidict file
+        getPiDict(port, hidden=True),
+        # provide compatibility with old-style pidict file (not dot-prefixed)
+        getPiDict(port, hidden=False),
+        # provide compatibility with old-style pidict file (short hostname)
+        getPiDict(port, hidden=True, hostname=getShortHostName()),
+        # provide compatibility with old-style pidict file (not dot-prefixed, short hostname
+        getPiDict(port, hidden=False, hostname=getShortHostName()),
+        # provide compatibility with old-style pidict file (long hostname)
+        getPiDict(port, hidden=True, hostname=getHostName()),
+        # provide compatibility with old-style pidict file (not dot-prefixed, long hostname)
+        getPiDict(port, hidden=False, hostname=getHostName())
+        ]
+
+    log_msg = ""
+    for filedict in filedicts:
+        log_msg += "Trying %s..."%filedict
+        if os.path.exists(filedict):
+            log_msg += "   ... OK\n"
+            break
+        else:
+            log_msg += "   ... not found\n"
+
+    if verbose():
+        print(log_msg)
+
+    return filedict
 #
 
 def killMyPort(port):
 #
 
 def killMyPort(port):
@@ -290,54 +287,61 @@ def killMyPort(port):
     Parameters:
     - port - port number
     """
     Parameters:
     - port - port number
     """
-    from salome_utils import getShortHostName, getHostName
-    print "Terminating SALOME on port %s..."%(port)
+    # bug fix: ensure port is an integer
+    if port:
+        port = int(port)
+
+    try:
+        import PortManager # do not remove! Test for PortManager availability!
+        filedict = getPiDict(port)
+        if not os.path.isfile(filedict): # removed by previous call, see (1)
+            if verbose():
+                print("SALOME on port %s: already removed by previous call"%port)
+            # Remove port from PortManager config file
+            try:
+                from PortManager import releasePort
+                if verbose():
+                    print("Removing port from PortManager configuration file")
+                releasePort(port)
+            except ImportError:
+                pass
+            return
+    except:
+        pass
 
     # try to shutdown session normally
     import threading, time
 
     # try to shutdown session normally
     import threading, time
-    threading.Thread(target=shutdownMyPort, args=(port,False)).start()
+    threading.Thread(target=shutdownMyPort, args=(port,True)).start()
     time.sleep(3) # wait a little, then kill processes (should be done if shutdown procedure hangs up)
 
     try:
     time.sleep(3) # wait a little, then kill processes (should be done if shutdown procedure hangs up)
 
     try:
-        import PortManager
-        filedict = getPiDict(port, hidden=True, with2809pid=False)
+        import PortManager # do not remove! Test for PortManager availability!
+        filedict = getPiDict(port)
+        #filedict = __guessPiDictFilename(port)
         import glob
         all_files = glob.glob("%s*"%filedict)
         for f in all_files:
             __killMyPort(port, f)
     except ImportError:
         import glob
         all_files = glob.glob("%s*"%filedict)
         for f in all_files:
             __killMyPort(port, f)
     except ImportError:
-        # new-style dot-prefixed pidict file
-        filedict = getPiDict(port, hidden=True)
-        # provide compatibility with old-style pidict file (not dot-prefixed)
-        if not os.path.exists(filedict): filedict = getPiDict(port, hidden=False)
-        # provide compatibility with old-style pidict file (short hostname)
-        if not os.path.exists(filedict): filedict = getPiDict(port, hidden=True,  hostname=getShortHostName())
-        # provide compatibility with old-style pidict file (not dot-prefixed, short hostname)
-        if not os.path.exists(filedict): filedict = getPiDict(port, hidden=False, hostname=getShortHostName())
-        # provide compatibility with old-style pidict file (long hostname)
-        if not os.path.exists(filedict): filedict = getPiDict(port, hidden=True,  hostname=getHostName())
-        # provide compatibility with old-style pidict file (not dot-prefixed, long hostname)
-        if not os.path.exists(filedict): filedict = getPiDict(port, hidden=False, hostname=getHostName())
+        filedict = __guessPiDictFilename(port)
         __killMyPort(port, filedict)
     #
         __killMyPort(port, filedict)
     #
+
     appliCleanOmniOrbConfig(port)
     pass
 
     appliCleanOmniOrbConfig(port)
     pass
 
-def killNotifdAndClean(port):
+def cleanApplication(port):
     """
     """
-    Kill notifd daemon and clean application running on the specified port.
+    Clean application running on the specified port.
     Parameters:
     - port - port number
     """
     Parameters:
     - port - port number
     """
+    # bug fix: ensure port is an integer
+    if port:
+        port = int(port)
+
     try:
         filedict=getPiDict(port)
     try:
         filedict=getPiDict(port)
-        with open(filedict, 'r') as f:
-            pids=pickle.load(f)
-            for d in pids:
-                for pid,process in d.items():
-                    if 'notifd' in process:
-                        cmd='kill -9 %d'% pid
-                        os.system(cmd)
         os.remove(filedict)
     except:
       #import traceback
         os.remove(filedict)
     except:
       #import traceback
@@ -345,23 +349,17 @@ def killNotifdAndClean(port):
       pass
 
     appliCleanOmniOrbConfig(port)
       pass
 
     appliCleanOmniOrbConfig(port)
+    pass
 
 def killMyPortSpy(pid, port):
     dt = 1.0
     while 1:
 
 def killMyPortSpy(pid, port):
     dt = 1.0
     while 1:
-        if sys.platform == "win32":
-            from win32pm import killpid
-            if killpid(int(pid), 0) != 0:
-                return
-        else:
-            from os import kill
-            try:
-                kill(int(pid), 0)
-            except OSError, e:
-                if e.errno != 3:
-                    return
-                break
-            pass
+        from salome_utils import killpid
+        ret = killpid(int(pid), 0)
+        if ret == 0:
+            break
+        elif ret < 0:
+            return
         from time import sleep
         sleep(dt)
         pass
         from time import sleep
         sleep(dt)
         pass
@@ -373,7 +371,7 @@ def killMyPortSpy(pid, port):
         orb = omniORB.CORBA.ORB_init(sys.argv, omniORB.CORBA.ORB_ID)
         import SALOME_NamingServicePy
         ns = SALOME_NamingServicePy.SALOME_NamingServicePy_i(orb)
         orb = omniORB.CORBA.ORB_init(sys.argv, omniORB.CORBA.ORB_ID)
         import SALOME_NamingServicePy
         ns = SALOME_NamingServicePy.SALOME_NamingServicePy_i(orb)
-        import SALOME
+        import SALOME #@UnresolvedImport @UnusedImport
         session = ns.Resolve("/Kernel/Session")
         assert session
     except:
         session = ns.Resolve("/Kernel/Session")
         assert session
     except:
@@ -393,10 +391,10 @@ def killMyPortSpy(pid, port):
 
 if __name__ == "__main__":
     if len(sys.argv) < 2:
 
 if __name__ == "__main__":
     if len(sys.argv) < 2:
-        print "Usage: "
-        print "  %s <port>" % os.path.basename(sys.argv[0])
-        print
-        print "Kills SALOME session running on specified <port>."
+        print("Usage: ")
+        print("  %s <port>" % os.path.basename(sys.argv[0]))
+        print()
+        print("Kills SALOME session running on specified <port>.")
         sys.exit(1)
         pass
     if sys.argv[1] == "--spy":
         sys.exit(1)
         pass
     if sys.argv[1] == "--spy":
@@ -407,6 +405,12 @@ if __name__ == "__main__":
             pass
         sys.exit(0)
         pass
             pass
         sys.exit(0)
         pass
+    try:
+        from salomeContextUtils import setOmniOrbUserPath #@UnresolvedImport
+        setOmniOrbUserPath()
+    except Exception as e:
+        print(e)
+        sys.exit(1)
     for port in sys.argv[1:]:
         killMyPort(port)
         pass
     for port in sys.argv[1:]:
         killMyPort(port)
         pass