11import os
22import sys
3+ import atexit
34from ctypes import *
45from tempfile import NamedTemporaryFile
56
1011__all__ = ['dbLoadDatabase' , 'iocInit' , 'interactive_ioc' ]
1112
1213
13- epicsExit = imports .epicsExit
14+ # tie in epicsAtExit() to interpreter lifecycle
15+ @atexit .register
16+ def epicsAtPyExit ():
17+ imports .epicsExitCallAtExits ()
1418
1519
1620def iocInit (dispatcher = None ):
@@ -36,17 +40,24 @@ def iocInit(dispatcher=None):
3640 imports .iocInit ()
3741
3842
39- def safeEpicsExit ():
43+ def safeEpicsExit (code = 0 ):
4044 '''Calls epicsExit() after ensuring Python exit handlers called.'''
41- if hasattr (sys , 'exitfunc' ):
45+ if hasattr (sys , 'exitfunc' ): # py 2.x
4246 try :
4347 # Calling epicsExit() will bypass any atexit exit handlers, so call
4448 # them explicitly now.
4549 sys .exitfunc ()
4650 finally :
4751 # Make sure we don't try the exit handlers more than once!
4852 del sys .exitfunc
49- epicsExit ()
53+
54+ elif hasattr (atexit , '_run_exitfuncs' ): # py 3.x
55+ atexit ._run_exitfuncs ()
56+
57+ # calls epicsExitCallAtExits()
58+ # and then OS exit()
59+ imports .epicsExit (code )
60+ epicsExit = safeEpicsExit
5061
5162# The following identifiers will be exported to interactive shell.
5263command_names = []
@@ -233,10 +244,10 @@ def call_f(*args):
233244# Hacked up exit object so that when soft IOC framework sends us an exit command
234245# we actually exit.
235246class Exiter :
236- def __repr__ (self ):
237- safeEpicsExit ( )
238- def __call__ (self ):
239- safeEpicsExit ( )
247+ def __repr__ (self ): # hack to exit when "called" with no parenthesis
248+ sys . exit ( 0 )
249+ def __call__ (self , code = 0 ):
250+ sys . exit ( code )
240251
241252exit = Exiter ()
242253command_names .append ('exit' )
@@ -305,7 +316,12 @@ def interactive_ioc(context = {}, call_exit = True):
305316 # This suppresses irritating exit message introduced by Python3. Alas,
306317 # this option is only available in Python 3.6!
307318 interact_args = dict (exitmsg = '' )
308- code .interact (local = dict (exports , ** context ), ** interact_args )
319+ try :
320+ code .interact (local = dict (exports , ** context ), ** interact_args )
321+ except SystemExit as e :
322+ if call_exit :
323+ safeEpicsExit (e .code )
324+ raise
309325
310326 if call_exit :
311- safeEpicsExit ()
327+ safeEpicsExit (0 )
0 commit comments