2 # -*- coding: iso-8859-1 -*-
3 # Copyright (C) 2021 CEA/DEN, EDF R&D
5 # This library is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU Lesser General Public
7 # License as published by the Free Software Foundation; either
8 # version 2.1 of the License, or (at your option) any later version.
10 # This library is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 # Lesser General Public License for more details.
15 # You should have received a copy of the GNU Lesser General Public
16 # License along with this library; if not, write to the Free Software
17 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 # \brief Module that provides services to launch SALOME
26 import sys, os, string, glob, time, pickle, re
29 from launchConfigureParser import verbose
30 from server import process_id, Server
33 from salomeContextUtils import ScriptAndArgsObjectEncoder
36 # -----------------------------------------------------------------------------
38 from killSalome import killAllPorts
42 kill servers from a previous SALOME execution, if needed,
43 on the CORBA port given in args of runSalome
46 from killSalomeWithPort import killMyPort
47 my_port=str(args['port'])
51 print("problem in killLocalPort()")
55 def givenPortKill(port):
57 kill servers from a previous SALOME execution, if needed,
58 on the same CORBA port
61 from killSalomeWithPort import killMyPort
66 print("problem in LocalPortKill(), killMyPort(%s)"%port)
70 def kill_salome(args):
72 Kill servers from previous SALOME executions, if needed;
73 depending on args 'killall' or 'portkill', kill all executions,
74 or only execution on the same CORBA port
79 elif args['portkill']:
80 givenPortKill(str(args['port']))
82 # -----------------------------------------------------------------------------
84 # Class definitions to launch CORBA Servers
87 class InterpServer(Server):
88 def __init__(self,args):
90 if sys.platform == "win32":
91 self.CMD=['cmd', '/c', 'start cmd.exe', '/K', 'python']
92 elif sys.platform == "darwin":
93 env_ld_library_path=['env', 'DYLD_LIBRARY_PATH=' + os.getenv("LD_LIBRARY_PATH")]
94 self.CMD=['xterm', '-e'] + env_ld_library_path + ['python']
96 env_ld_library_path=['env', 'LD_LIBRARY_PATH=' + os.getenv("LD_LIBRARY_PATH")]
97 self.CMD=['xterm', '-e'] + env_ld_library_path + ['python']
102 print("INTERPSERVER::command = ", command)
104 pid = subprocess.Popen(command).pid
105 process_id[pid]=self.CMD
110 def get_cata_path(list_modules,modules_root_dir):
111 """Build a list of catalog paths (cata_path) to initialize the ModuleCatalog server
116 for module in list_modules:
117 if module in modules_root_dir:
118 module_root_dir=modules_root_dir[module]
119 module_cata=module+"Catalog.xml"
120 cata_file=os.path.join(module_root_dir, "share",setenv.salome_subdir, "resources",module.lower(), module_cata)
122 if os.path.exists(cata_file):
123 cata_path.append(cata_file)
124 modules_cata[module]=cata_file
126 cata_file=os.path.join(module_root_dir, "share",setenv.salome_subdir, "resources", module_cata)
127 if os.path.exists(cata_file):
128 cata_path.append(cata_file)
129 modules_cata[module]=cata_file
131 for path in os.getenv("SALOME_CATALOGS_PATH","").split(os.pathsep):
132 if os.path.exists(path):
133 for cata_file in glob.glob(os.path.join(path,"*Catalog.xml")):
134 module_name= os.path.basename(cata_file)[:-11]
135 if module_name not in modules_cata:
136 cata_path.append(cata_file)
137 modules_cata[module_name]=cata_file
142 class LoggerServer(Server):
143 def __init__(self,args):
146 from salome_utils import generateFileName, getLogDir
147 logfile = generateFileName( getLogDir(),
153 print("===========================================================")
154 print("Logger server: put log to the file:")
156 print("===========================================================")
157 self.CMD=['SALOME_Logger_Server', logfile]
159 pass # end of LoggerServer class
163 class SessionServer(Server):
164 def __init__(self,args,modules_list,modules_root_dir):
165 self.args = args.copy()
166 # Bug 11512 (Problems with runSalome --xterm on Mandrake and Debian Sarge)
167 #self.args['xterm']=0
170 self.SCMD1=['SALOME_Session_Server_No_Server']
171 if "SQUISH_PREFIX" in os.environ:
172 if platform.system() == "Windows" :
173 self.SCMD1 = [os.path.join(os.getenv("SQUISH_PREFIX"), "bin", "dllpreload.exe"),os.path.join(os.getenv("SQUISH_SALOME_PATH"), "W64", "GUI", "bin", "salome", self.SCMD1[0])]
175 os.environ["LD_LIBRARY_PATH"] = os.environ["SQUISH_PREFIX"] + "/lib:" + os.environ["LD_LIBRARY_PATH"]
177 if 'launcher' in self.args:
178 pos = args['launcher'].find(":")
180 self.SCMD1+=['-ORBInitRef']
181 machine = args['launcher'][0:pos]
182 port = args['launcher'][pos+1:]
183 self.SCMD1+=["NameService=corbaname::" + machine + ":" + port]
184 if 'registry' in self.args['embedded']:
185 self.SCMD1+=['--with','Registry',
186 '(','--salome_session','theSession',')']
187 if 'moduleCatalog' in self.args['embedded']:
188 self.SCMD1+=['--with','ModuleCatalog','(','-common']
189 home_dir=os.path.expanduser("~")
190 #if home_dir is not None:
191 # self.SCMD2+=['-personal',os.path.join(home_dir,'Salome','resources','CatalogModulePersonnel.xml')]
193 if 'study' in self.args['embedded']:
194 self.SCMD2+=['--with','SALOMEDS','(',')']
195 if 'cppContainer' in self.args['embedded']:
196 self.SCMD2+=['--with','Container','(','FactoryServer',')']
197 if 'SalomeAppEngine' in self.args['embedded']:
198 self.SCMD2+=['--with','SalomeAppEngine','(',')']
200 if 'cppContainer' in self.args['standalone'] or 'cppContainer' in self.args['embedded']:
202 if 'pyContainer' in self.args['standalone'] or 'pyContainer' in self.args['embedded']:
203 raise Exception('Python containers no longer supported')
205 session_gui = self.args.get('session_gui', True)
207 self.SCMD2+=['--hide-desktop']
209 if not self.args['splash']:
210 self.SCMD2+=['--hide-splash']
212 if self.args['study_hdf'] is not None:
213 self.SCMD2+=['--study-hdf=%s'%self.args['study_hdf']]
216 if 'pyscript' in self.args and len(self.args['pyscript']) > 0:
217 msg = json.dumps(self.args['pyscript'], cls=ScriptAndArgsObjectEncoder)
218 self.SCMD2+=['--pyscript=%s'%(msg)]
222 if self.args['noexcepthandler']:
223 self.SCMD2+=['--no-exception-handler']
224 if 'user_config' in self.args:
225 self.SCMD2+=['--resources=%s'%self.args['user_config']]
226 if 'modules' in self.args:
228 #keep only modules with GUI
229 for m in modules_list:
230 if m not in modules_root_dir:
231 list_modules.insert(0,m)
233 fr1 = os.path.join(modules_root_dir[m],"share","salome","resources",m.lower(),"SalomeApp.xml")
234 fr2 = os.path.join(modules_root_dir[m],"share","salome","resources","SalomeApp.xml")
235 if os.path.exists(fr1) or os.path.exists(fr2):
236 list_modules.insert(0,m)
237 list_modules.reverse()
238 self.SCMD2+=['--modules (%s)' % ":".join(list_modules)]
240 if 'language' in self.args:
241 self.SCMD2+=['--language=%s' % self.args['language']]
246 def setpath(self,modules_list,modules_root_dir):
247 list_modules = modules_list[:]
248 list_modules.reverse()
249 if self.args["gui"] :
250 list_modules = ["KERNEL", "GUI"] + list_modules
252 list_modules = ["KERNEL"] + list_modules
254 cata_path=get_cata_path(list_modules,modules_root_dir)
256 if ("gui" in self.args) & ('moduleCatalog' in self.args['embedded']):
257 #Use '::' instead ":" because drive path with "D:\" is invalid on windows platform
258 self.CMD=self.SCMD1 + ['"' + '"::"'.join(cata_path) + '"'] + self.SCMD2
260 self.CMD=self.SCMD1 + self.SCMD2
261 if 'test' in self.args:
262 self.CMD+=['-test'] + self.args['test']
263 elif 'play' in self.args:
264 self.CMD+=['-play'] + self.args['play']
266 if self.args["gdb_session"] or self.args["ddd_session"]:
267 f = open(".gdbinit4salome", "w")
269 args = " ".join(self.CMD[1:])
270 args = args.replace("(", "\(")
271 args = args.replace(")", "\)")
275 if self.args["ddd_session"]:
276 self.CMD = ["ddd", "--command=.gdbinit4salome", self.CMD[0]]
277 elif self.args["gdb_session"]:
278 self.CMD = ["xterm", "-e", "gdb", "--command=.gdbinit4salome", self.CMD[0]]
282 if self.args["valgrind_session"]:
284 val = os.getenv("VALGRIND_OPTIONS")
288 self.CMD = l + self.CMD
291 # -----------------------------------------------------------------------------
294 """Salome Session Graphic User Interface activation"""
298 import SALOME_ModuleCatalog
299 import SALOME_Session_idl
300 session=clt.waitNS("/Kernel/Session",SALOME.Session)
301 session.GetInterface()
303 # -----------------------------------------------------------------------------
305 def startSalome(args, modules_list, modules_root_dir):
308 """Launch all SALOME servers requested by args"""
309 init_time = os.times()
311 if verbose(): print("startSalome ", args)
314 # Set server launch command
316 if 'server_launch_mode' in args:
317 Server.set_server_launch_mode(args['server_launch_mode'])
320 # Wake up session option
322 if args['wake_up_session']:
323 if "OMNIORB_CONFIG" not in os.environ:
324 from salome_utils import generateFileName
325 omniorbUserPath = os.getenv("OMNIORB_USER_PATH")
327 if omniorbUserPath is not None:
328 kwargs["with_username"]=True
330 last_running_config = generateFileName(omniorbUserPath, prefix="omniORB",
335 os.environ['OMNIORB_CONFIG'] = last_running_config
340 # Initialisation ORB and Naming Service
346 # Wake up session option
348 if args['wake_up_session']:
352 import SALOME_ModuleCatalog
353 import SALOME_Session_idl
354 session = clt.waitNS("/Kernel/Session",SALOME.Session)
355 status = session.GetStatSession()
357 from salome_utils import getPortNumber
358 port = getPortNumber()
361 msg += "Session GUI for port number %s is already active."%(port)
363 msg += "If you which to wake up another session,"
365 msg += "please use variable OMNIORB_CONFIG"
367 msg += "to get the correct session object in naming service."
368 sys.stdout.write(msg+"\n")
371 session.GetInterface()
372 args["session_object"] = session
375 # Launch Logger Server (optional)
376 # and wait until it is registered in naming service
380 myServer=LoggerServer(args)
382 clt.waitLogger("Logger")
386 from Utils_Identity import getShortHostName
388 if os.getenv("HOSTNAME") == None:
389 if os.getenv("HOST") == None:
390 os.environ["HOSTNAME"]=getShortHostName()
392 os.environ["HOSTNAME"]=os.getenv("HOST")
394 theComputer = getShortHostName()
396 # ASV start GUI without Loader
398 # session.GetInterface()
401 # additional external python interpreters
407 nbaddi = args['interp']
410 traceback.print_exc()
411 print("-------------------------------------------------------------")
412 print("-- to get an external python interpreter:runSalome --interp=1")
413 print("-------------------------------------------------------------")
415 if verbose(): print("additional external python interpreters: ", nbaddi)
417 for i in range(nbaddi):
419 anInterp=InterpServer(args)
422 # set PYTHONINSPECT variable (python interpreter in interactive mode)
424 os.environ["PYTHONINSPECT"]="1"
430 # -----------------------------------------------------------------------------
432 def useSalome(args, modules_list, modules_root_dir):
434 Launch all SALOME servers requested by args,
435 save list of process, give info to user,
436 show registered objects in Naming Service.
442 startSalome(args, modules_list, modules_root_dir)
445 traceback.print_exc()
448 print("--- Error during Salome launch ---")
452 from addToKillList import addToKillList
453 from killSalomeWithPort import getPiDict
455 filedict = getPiDict(args['port'])
456 for pid, cmd in list(process_id.items()):
457 addToKillList(pid, cmd, args['port'])
463 SalomeAppSLConfig=os.getenv("SalomeAppConfig","")
464 os.putenv("SalomeAppSLConfig", SalomeAppSLConfig)
467 if args["gui"] and not args['launcher_only']:
468 mySessionServ = SessionServer(args,args['modules'],modules_root_dir)
469 mySessionServ.setpath(modules_list,modules_root_dir)
474 if verbose(): print("""
475 Saving of the dictionary of Salome processes in %s
476 To kill SALOME processes from a console (kill all sessions from all ports):
478 To kill SALOME from the present interpreter, if it is not closed :
479 killLocalPort() --> kill this session
480 (use CORBA port from args of runSalome)
481 givenPortKill(port) --> kill a specific session with given CORBA port
482 killAllPorts() --> kill all sessions
484 runSalome, with --killall option, starts with killing
485 the processes resulting from the previous execution.
489 # Print Naming Service directory list
495 print(" --- registered objects tree in Naming Service ---")
499 # run python scripts, passed as command line arguments
501 if 'gui' in args and 'session_gui' in args:
502 if not args['gui'] or not args['session_gui']:
503 if 'study_hdf' in args:
504 toopen = args['study_hdf']
507 salome.salome_init(path=toopen)
508 if 'pyscript' in args:
509 toimport = args['pyscript']
510 from salomeContextUtils import formatScriptsAndArgs
511 command = formatScriptsAndArgs(toimport, escapeSpaces=True)
513 proc = subprocess.Popen(command, shell=True)
514 addToKillList(proc.pid, command, args['port'])
516 if res: sys.exit(1) # if there's an error when executing script, we should explicitly exit
520 def execScript(script_path):
521 print('executing', script_path)
522 sys.path.insert(0, os.path.realpath(os.path.dirname(script_path)))
523 exec(compile(open(script_path).read(), script_path, 'exec'),globals())
526 # -----------------------------------------------------------------------------
528 def registerEnv(args, modules_list, modules_root_dir):
530 Register args, modules_list, modules_root_dir in a file
531 for further use, when SALOME is launched embedded in an other application.
533 from salome_utils import getTmpDir
534 fileEnv = getTmpDir()
535 from salome_utils import getUserName
536 fileEnv += getUserName() + "_" + str(args['port']) \
537 + '_' + args['appname'].upper() + '_env'
538 fenv=open(fileEnv,'w')
539 pickle.dump((args, modules_list, modules_root_dir),fenv)
541 os.environ["SALOME_LAUNCH_CONFIG"] = fileEnv
543 # -----------------------------------------------------------------------------
546 """Salome Launch, when embedded in other application"""
547 fileEnv = os.environ["SALOME_LAUNCH_CONFIG"]
548 fenv=open(fileEnv,'r')
549 args, modules_list, modules_root_dir = pickle.load(fenv)
552 from searchFreePort import searchFreePort
553 searchFreePort(args, 0)
554 clt = useSalome(args, modules_list, modules_root_dir)
557 # -----------------------------------------------------------------------------
559 def addToPidict(args):
561 from addToKillList import addToKillList
562 for pid, cmd in list(process_id.items()):
563 addToKillList(pid, cmd, args['port'])
565 # -----------------------------------------------------------------------------
567 def main(exeName=None):
568 """Salome launch as a main application"""
570 from salome_utils import getHostName
571 keep_env = not os.getenv('SALOME_PLEASE_SETUP_ENVIRONMENT_AS_BEFORE')
572 args, modules_list, modules_root_dir = setenv.get_config(exeName=exeName, keepEnvironment=keep_env)
573 print("runSalome running on %s" % getHostName())
577 setenv.set_env(args, modules_list, modules_root_dir, keepEnvironment=keep_env)
578 clt = useSalome(args, modules_list, modules_root_dir)
581 # -----------------------------------------------------------------------------
583 def foreGround(clt, args):
585 if "session_object" not in args:
587 session = args["session_object"]
589 # Wait until gui is arrived
599 status = session.GetStatSession()
600 gui_detected = status.activeGUI
601 session_pid = session.getPID()
606 from time import sleep
616 from salome_utils import getPortNumber
617 port = getPortNumber()
620 if sys.platform == "win32":
621 server.CMD = [os.getenv("PYTHONBIN"), "-m", "killSalomeWithPort", "--spy", "%s"%(session_pid or os.getpid()), "%s"%(port)]
623 server.CMD = ["killSalomeWithPort.py", "--spy", "%s"%(session_pid or os.getpid()), "%s"%(port)]
625 # os.system("killSalomeWithPort.py --spy %s %s &"%(os.getpid(), port))
631 status = session.GetStatSession()
632 assert status.activeGUI
635 from time import sleep
639 except KeyboardInterrupt:
640 from killSalomeWithPort import killMyPort
649 test = args['gui'] and args['session_gui']
650 test = test or args['wake_up_session']
652 # The next test covers the --pinter option or if var PYTHONINSPECT is set
654 test = test and not os.environ.get('PYTHONINSPECT')
656 # The next test covers the python -i $KERNEL_ROOT_DIR/bin/salome/runSalome.py case
659 from ctypes import POINTER, c_int, cast, pythonapi
660 iflag_ptr = cast(pythonapi.Py_InteractiveFlag, POINTER(c_int))
661 test = test and not iflag_ptr.contents.value
665 # test = test and os.getenv("SALOME_TEST_MODE", "0") != "1"
666 test = test and args['foreground']
669 from time import sleep
671 foreGround(clt, args)
676 # -----------------------------------------------------------------------------
678 if __name__ == "__main__":