Salome HOME
Increase time let to SALOME_Session_Server process to startup and retrieve its PID...
[modules/kernel.git] / bin / runSalome.py
1 #!/usr/bin/env python3
2 #  -*- coding: iso-8859-1 -*-
3 # Copyright (C) 2022  CEA/DEN, EDF R&D, OPEN CASCADE
4 #
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.
9 #
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.
14 #
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
18 #
19 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 #
21
22 ## @package runSalome
23 # \brief Module that provides services to launch SALOME
24 #
25
26 import sys, os, string, glob, time, pickle, re
27 import orbmodule
28 import setenv
29 from server import process_id, Server
30 import json
31 import subprocess
32 from salomeContextUtils import ScriptAndArgsObjectEncoder
33 import runSalomeNoServer
34 import runSalomeCommon
35 import platform
36 import logging
37 logger = logging.getLogger()
38
39 # -----------------------------------------------------------------------------
40
41 from killSalome import killAllPorts
42
43 def kill_salome(args):
44     """
45     Kill servers from previous SALOME executions, if needed;
46     depending on args 'killall' or 'portkill', kill all executions,
47     or only execution on the same CORBA port
48     """
49
50     if args['killall']:
51         killAllPorts()
52 #
53 # -----------------------------------------------------------------------------
54
55 def startGUI(clt):
56     """Salome Session Graphic User Interface activation"""
57     import Engines
58     import SALOME
59     import SALOMEDS
60     import SALOME_ModuleCatalog
61     import SALOME_Session_idl
62     session=clt.waitNS("/Kernel/Session",SALOME.Session)
63     session.GetInterface()
64
65 # -----------------------------------------------------------------------------
66
67 def startSalome(args, modules_list, modules_root_dir):
68     """Launch all SALOME servers requested by args"""
69     init_time = os.times()
70
71     logger.debug("startSalome : {} ".format(args))
72
73     ior_fakens_filename = None
74
75     # Launch  Session Server (to show splash ASAP)
76     #
77
78     if args["gui"] and not args['launcher_only']:
79         mySessionServ = runSalomeNoServer.NoSessionServer(args,args['modules'],modules_root_dir)
80         mySessionServ.setpath(modules_list,modules_root_dir)
81         mySessionServ.run()
82         ior_fakens_filename = mySessionServ.iorfakens
83         logger.debug("Rendez-vous file for to retrieve IOR of session is \"{}\"".format(ior_fakens_filename))
84     
85     end_time = os.times()
86
87     #
88     # Wait until Session Server is registered in naming service
89     #
90     logger.debug("Start SALOME, elapsed time : %5.1f seconds"% (end_time[4] - init_time[4]))
91
92     #
93     # additional external python interpreters
94     #
95     nbaddi=0
96
97     try:
98         if 'interp' in args:
99             nbaddi = args['interp']
100     except Exception:
101         import traceback
102         traceback.print_exc()
103         logger.error("-------------------------------------------------------------")
104         logger.error("-- to get an external python interpreter:runSalome --interp=1")
105         logger.error("-------------------------------------------------------------")
106
107     logger.debug("additional external python interpreters: {}".format(nbaddi))
108     if nbaddi:
109         for i in range(nbaddi):
110             anInterp=runSalomeCommon.InterpServer(args)
111             anInterp.run()
112
113     # set PYTHONINSPECT variable (python interpreter in interactive mode)
114     if args['pinter']:
115         os.environ["PYTHONINSPECT"]="1"
116         try:
117             import readline
118         except ImportError:
119             pass
120
121     return ior_fakens_filename
122
123 # -----------------------------------------------------------------------------
124
125 def useSalome(args, modules_list, modules_root_dir):
126     """
127     Launch all SALOME servers requested by args,
128     save list of process, give info to user,
129     show registered objects in Naming Service.
130     """
131     global process_id
132     ior_fakens_filename = None
133     try:
134         ior_fakens_filename = startSalome(args, modules_list, modules_root_dir)
135     except Exception:
136         import traceback
137         traceback.print_exc()
138         logger.error("--- Error during Salome launch ---")
139
140     # print(process_id)
141
142     from addToKillList import addToKillList
143     from killSalomeWithPort import getPiDict
144
145     filedict = getPiDict(args['port'])
146     for pid, cmd in list(process_id.items()):
147         addToKillList(pid, cmd, args['port'])
148         pass
149
150     logger.debug("""
151     Saving of the dictionary of Salome processes in %s
152     To kill SALOME processes from a console (kill all sessions from all ports):
153       python killSalome.py
154     To kill SALOME from the present interpreter, if it is not closed :
155       killLocalPort()      --> kill this session
156                                (use CORBA port from args of runSalome)
157       givenPortKill(port)  --> kill a specific session with given CORBA port
158       killAllPorts()       --> kill all sessions
159
160     runSalome, with --killall option, starts with killing
161     the processes resulting from the previous execution.
162     """%filedict)
163
164     return ior_fakens_filename
165
166 def execScript(script_path):
167     print('executing', script_path)
168     sys.path.insert(0, os.path.realpath(os.path.dirname(script_path)))
169     exec(compile(open(script_path).read(), script_path, 'exec'),globals())
170     del sys.path[0]
171
172 # -----------------------------------------------------------------------------
173
174 def main(exeName=None):
175     """Salome launch as a main application"""
176     keep_env = not os.getenv('SALOME_PLEASE_SETUP_ENVIRONMENT_AS_BEFORE')
177     args, modules_list, modules_root_dir = setenv.get_config(exeName=exeName, keepEnvironment=keep_env)
178     runSalomeCommon.setVerbose(args["verbosity"])
179     kill_salome(args)
180     # --
181     setenv.set_env(args, modules_list, modules_root_dir, keepEnvironment=keep_env)
182     ior_fakens_filename = useSalome(args, modules_list, modules_root_dir)
183     # Management of -t <script.py>
184     toimport = []
185     env = os.environ
186     if 'gui' in args and 'session_gui' in args:
187         if not args['gui'] or not args['session_gui']:
188             if 'study_hdf' in args:
189                 toopen = args['study_hdf']
190                 if toopen:
191                     os.environ["PATH_TO_STUDY_FILE_TO_INITIATE"] = toopen
192                     logger.debug("An input Study has been specified {} -> pass it with PATH_TO_STUDY_FILE_TO_INITIATE env var".format(toopen))
193             if 'pyscript' in args:
194                 toimport = args['pyscript']
195     from salomeContextUtils import formatScriptsAndArgs
196     from addToKillList import addToKillList
197     command = formatScriptsAndArgs(toimport, escapeSpaces=True)
198     if command:
199         logger.debug("Launching following shell command : {}".format(str(command)))
200         proc = subprocess.Popen(command, shell=True, env = env)
201         addToKillList(proc.pid, command)
202         res = proc.wait()
203         if res: sys.exit(1) 
204     return args, ior_fakens_filename
205
206 # -----------------------------------------------------------------------------
207
208 def foreGround(args, ior_fakens_filename):
209     # --
210     import os
211     gui_detected = False
212     dt = 0.1
213     nbtot = 200
214     nb = 0
215     if ior_fakens_filename is None:
216         logger.warn("No file set to host IOR of the fake naming server")
217         return
218     if not os.path.exists(ior_fakens_filename):
219         logger.warn("No file {} set to host IOR of the fake naming server does not exit !")
220         return
221     import CORBA
222     import Engines
223     import SALOME
224     from time import sleep
225     orb = CORBA.ORB_init([''], CORBA.ORB_ID)
226     ior_fakens = None
227     session = None
228     while True:
229         try:
230             ior_fakens = orb.string_to_object(open(ior_fakens_filename).read())
231             session = orb.string_to_object(ior_fakens.Resolve("/Kernel/Session").decode())
232         except Exception:
233             pass
234         if ( session is not None ) and (not CORBA.is_nil(session)):
235             try:
236                 os.remove(ior_fakens_filename)
237                 logger.debug("File {} has been removed".format(ior_fakens_filename))
238             except:
239                 pass
240             logger.debug("Session in child process has been found ! yeah ! {}".format(str(session)))
241             break
242         sleep(dt)
243         nb += 1
244         logger.debug("Unfortunately Session not found into {} : Sleep and retry. {}/{}".format(ior_fakens_filename,nb,nbtot))
245         if nb == nbtot:
246             break
247     nb = 0
248     # --
249     # Wait until gui is arrived
250     # tmax = nbtot * dt
251     # --
252     session_pid = None
253     while 1:
254         try:
255             status = session.GetStatSession()
256             gui_detected = status.activeGUI
257             session_pid = session.getPID()
258             logger.debug("Process of the session under monitoring {}".format(session_pid))
259         except Exception:
260             pass
261         if gui_detected:
262             break
263         sleep(dt)
264         nb += 1
265         if nb == nbtot:
266             break
267         pass
268     # --
269     if not gui_detected:
270         return
271     # --
272     from salome_utils import getPortNumber
273     port = getPortNumber()
274     # --
275     dt = 1.0
276     try:
277         while 1:
278             try:
279                 status = session.GetStatSession()
280                 assert status.activeGUI
281             except Exception:
282                 logger.debug("Process of the session under monitoring {} has vanished !".format(session_pid))
283                 break
284             from time import sleep
285             sleep(dt)
286             pass
287         pass
288     except KeyboardInterrupt:
289         logger.debug("Keyboard requested : killing all process attached to port {}".format(port))
290     finally:
291         from killSalomeWithPort import killProcessSSL
292         killProcessSSL(port,[session_pid])
293     return
294 #
295
296 def runSalome():
297     args, ior_fakens_filename = main()
298     # --
299     test = args['gui'] and args['session_gui']
300     test = test or args['wake_up_session']
301     # --
302     # The next test covers the --pinter option or if var PYTHONINSPECT is set
303     # --
304     test = test and not os.environ.get('PYTHONINSPECT')
305     # --
306     # The next test covers the python -i $KERNEL_ROOT_DIR/bin/salome/runSalome.py case
307     # --
308     try:
309         from ctypes import POINTER, c_int, cast, pythonapi
310         iflag_ptr = cast(pythonapi.Py_InteractiveFlag, POINTER(c_int))
311         test = test and not iflag_ptr.contents.value
312     except Exception:
313         pass
314     # --
315 #    test = test and os.getenv("SALOME_TEST_MODE", "0") != "1"
316     test = test and args['foreground']
317     # --
318     if test:
319         from time import sleep
320         sleep(3.0)
321         foreGround(args, ior_fakens_filename)
322         pass
323     pass
324 #
325
326 # -----------------------------------------------------------------------------
327
328 if __name__ == "__main__":
329     runSalome()
330 #