X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=bin%2FPortManager.py;h=e0584ac81529000f029ad5267f0b1b6a66dbd8b9;hb=8e13e88d05d970cc47659054136f16aa0361b2fc;hp=0d01ce950faa2c8bd90e4a002631014bc835fe2b;hpb=fd23426f32248e9715e02a133487bd3bff8f54ad;p=modules%2Fkernel.git diff --git a/bin/PortManager.py b/bin/PortManager.py index 0d01ce950..e0584ac81 100644 --- a/bin/PortManager.py +++ b/bin/PortManager.py @@ -1,6 +1,6 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # -*- coding: iso-8859-1 -*- -# Copyright (C) 2007-2014 CEA/DEN, EDF R&D, OPEN CASCADE +# Copyright (C) 2007-2019 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 @@ -25,17 +25,21 @@ import os import sys try: - import cPickle as pickle + import cPickle as pickle #@UnusedImport except: - import pickle + import pickle #@Reimport + +__PORT_MIN_NUMBER = 2810 +__PORT_MAX_NUMBER = 2910 import logging def createLogger(): logger = logging.getLogger(__name__) -# logger.setLevel(logging.DEBUG) + #logger.setLevel(logging.DEBUG) + logger.setLevel(logging.INFO) ch = logging.StreamHandler() ch.setLevel(logging.DEBUG) - formatter = logging.Formatter("%(levelname)s:%(threadName)s:%(message)s") + formatter = logging.Formatter("%(levelname)s:%(threadName)s:%(pathname)s[%(lineno)s]%(message)s") ch.setFormatter(formatter) logger.addHandler(ch) return logger @@ -43,8 +47,9 @@ def createLogger(): logger = createLogger() #------------------------------------ -# A file locker (Linux only) +# A file locker def __acquire_lock(lock): + logger.debug("ACQUIRE LOCK") if sys.platform == "win32": import msvcrt # lock 1 byte: file is supposed to be zero-byte long @@ -52,34 +57,46 @@ def __acquire_lock(lock): else: import fcntl fcntl.flock(lock, fcntl.LOCK_EX) + logger.debug("LOCK ACQUIRED") # def __release_lock(lock): + logger.debug("RELEASE LOCK") if sys.platform == "win32": import msvcrt msvcrt.locking(lock.fileno(), msvcrt.LK_UNLCK, 1) else: import fcntl fcntl.flock(lock, fcntl.LOCK_UN) + logger.debug("LOCK RELEASED") # +#------------------------------------ def _getConfigurationFilename(): omniorbUserPath = os.getenv("OMNIORB_USER_PATH") from salome_utils import generateFileName portmanager_config = generateFileName(omniorbUserPath, - prefix="omniORB", + prefix="salome", suffix="PortManager", extension="cfg", hidden=True) import tempfile temp = tempfile.NamedTemporaryFile() - lock_file = os.path.join(os.path.dirname(temp.name), ".omniORB_PortManager.lock") + lock_file = os.path.join(os.path.dirname(temp.name), ".salome_PortManager.lock") + try: + with open(lock_file, 'wb'): + pass + except IOError: + pass temp.close() return (portmanager_config, lock_file) # -def __isPortUsed(port, busy_ports): +def __isPortUsed(port, config): + busy_ports = [] + for ports in config.values(): + busy_ports += ports return (port in busy_ports) or __isNetworkConnectionActiveOnPort(port) # @@ -87,10 +104,26 @@ def __isNetworkConnectionActiveOnPort(port): # :NOTE: Under windows: # netstat options -l and -t are unavailable # grep command is unavailable - from subprocess import Popen, PIPE - (stdout, stderr) = Popen(['netstat','-an'], stdout=PIPE).communicate() - import StringIO - buf = StringIO.StringIO(stdout) + if sys.platform == "win32": + cmd = ['netstat','-a','-n','-p','tcp'] + else: + cmd = ['netstat','-ant'] + pass + + err = None + try: + from subprocess import Popen, PIPE, STDOUT + p = Popen(cmd, stdout=PIPE, stderr=STDOUT) + out, err = p.communicate() + except: + print("Error when trying to access active network connections.") + if err: print(err) + import traceback + traceback.print_exc() + return False + + from io import StringIO + buf = StringIO(out.decode('utf-8', 'ignore')) ports = buf.readlines() # search for TCP - LISTEN connections import re @@ -101,48 +134,55 @@ def __isNetworkConnectionActiveOnPort(port): if p == port: return True except: pass + return False # -def getPort(preferedPort=None): +def getPort(preferredPort=None): logger.debug("GET PORT") config_file, lock_file = _getConfigurationFilename() oldmask = os.umask(0) - with open(lock_file, 'w') as lock: + with open(lock_file, 'rb') as lock: # acquire lock __acquire_lock(lock) # read config - config = {'busy_ports':[]} + config = {} logger.debug("read configuration file") try: - with open(config_file, 'r') as f: + with open(config_file, 'rb') as f: config = pickle.load(f) - except IOError: # empty file - pass + except: + logger.info("Problem loading PortManager file: %s"%config_file) + # In this case config dictionary is reset - logger.debug("load busy_ports: %s"%str(config["busy_ports"])) + logger.debug("load config: %s"%str(config)) + appli_path = os.getenv("ABSOLUTE_APPLI_PATH", "unknown") + try: + config[appli_path] + except KeyError: + config[appli_path] = [] # append port - busy_ports = config["busy_ports"] - port = preferedPort - if not port or __isPortUsed(port, busy_ports): - port = 2810 - while __isPortUsed(port, busy_ports): - if port == 2810+100: + port = preferredPort + if not port or __isPortUsed(port, config): + port = __PORT_MIN_NUMBER + while __isPortUsed(port, config): + if port == __PORT_MAX_NUMBER: msg = "\n" msg += "Can't find a free port to launch omniNames\n" msg += "Try to kill the running servers and then launch SALOME again.\n" - raise RuntimeError, msg + raise RuntimeError(msg) + logger.debug("Port %s seems to be busy"%str(port)) port = port + 1 logger.debug("found free port: %s"%str(port)) - config["busy_ports"].append(port) + config[appli_path].append(port) # write config - logger.debug("write busy_ports: %s"%str(config["busy_ports"])) + logger.debug("write config: %s"%str(config)) try: - with open(config_file, 'w') as f: - pickle.dump(config, f) + with open(config_file, 'wb') as f: + pickle.dump(config, f, protocol=0) except IOError: pass @@ -160,33 +200,36 @@ def releasePort(port): logger.debug("RELEASE PORT (%s)"%port) config_file, lock_file = _getConfigurationFilename() - with open(lock_file, 'w') as lock: + oldmask = os.umask(0) + with open(lock_file, 'rb') as lock: # acquire lock __acquire_lock(lock) # read config - config = {'busy_ports':[]} + config = {} logger.debug("read configuration file") try: - with open(config_file, 'r') as f: + with open(config_file, 'rb') as f: config = pickle.load(f) except IOError: # empty file pass - logger.debug("load busy_ports: %s"%str(config["busy_ports"])) + logger.debug("load config: %s"%str(config)) + appli_path = os.getenv("ABSOLUTE_APPLI_PATH", "unknown") + try: + config[appli_path] + except KeyError: + config[appli_path] = [] # remove port from list - busy_ports = config["busy_ports"] - - if port in busy_ports: - busy_ports.remove(port) - config["busy_ports"] = busy_ports + ports_info = config[appli_path] + config[appli_path] = [x for x in ports_info if x != port] # write config - logger.debug("write busy_ports: %s"%str(config["busy_ports"])) + logger.debug("write config: %s"%str(config)) try: - with open(config_file, 'w') as f: - pickle.dump(config, f) + with open(config_file, 'wb') as f: + pickle.dump(config, f, protocol=0) except IOError: pass @@ -194,28 +237,52 @@ def releasePort(port): __release_lock(lock) logger.debug("released port port: %s"%str(port)) + + os.umask(oldmask) # def getBusyPorts(): config_file, lock_file = _getConfigurationFilename() - with open(lock_file, 'w') as lock: + oldmask = os.umask(0) + with open(lock_file, 'wb') as lock: # acquire lock __acquire_lock(lock) # read config - config = {'busy_ports':[]} + config = {} logger.debug("read configuration file") try: - with open(config_file, 'r') as f: + with open(config_file, 'rb') as f: config = pickle.load(f) except IOError: # empty file pass - logger.debug("load busy_ports: %s"%str(config["busy_ports"])) + logger.debug("load config: %s"%str(config)) + appli_path = os.getenv("ABSOLUTE_APPLI_PATH", "unknown") + try: + config[appli_path] + except KeyError: + config[appli_path] = [] + + # Scan all possible ports to determine which ones are owned by other applications + ports_info = { 'this': [], 'other': [] } + my_busy_ports = config[appli_path] + for port in range(__PORT_MIN_NUMBER, __PORT_MAX_NUMBER): + if __isPortUsed(port, config): + logger.debug("Port %s seems to be busy"%str(port)) + if port in my_busy_ports: + ports_info["this"].append(port) + else: + ports_info["other"].append(port) + + logger.debug("all busy_ports: %s"%str(ports_info)) + + sorted_ports = { 'this': sorted(ports_info['this']), + 'other': sorted(ports_info['other']) } - busy_ports = config["busy_ports"] # release lock __release_lock(lock) - return busy_ports + os.umask(oldmask) + return sorted_ports #