Fixup atexit handling#35
Conversation
allow interactive_ioc(call_exit=False) to cleanup and exit cleanly.
Codecov Report
@@ Coverage Diff @@
## master #35 +/- ##
==========================================
- Coverage 85.74% 85.50% -0.25%
==========================================
Files 13 13
Lines 807 828 +21
==========================================
+ Hits 692 708 +16
- Misses 115 120 +5
Continue to review full report at Codecov.
|
thomascobb
left a comment
There was a problem hiding this comment.
I'm a bit hazy on the details of how we stop the IOC cleanly, so my comments reflect that...
| def __call__(self): | ||
| safeEpicsExit() | ||
| def __repr__(self): # hack to exit when "called" with no parenthesis | ||
| sys.exit(0) |
There was a problem hiding this comment.
I guess this will make code.interact raise SystemExit which will call safeEpicsExit, Why do we call sys.exit() here rather than safeEpicsExit?
There was a problem hiding this comment.
sys.exit() will work the same regardless of how interactive_ioc() is called. This keeps the handling of call_exit=True vs. call_exit=False contained to interactive_ioc() where SystemExit is now caught.
Araneidae
left a comment
There was a problem hiding this comment.
Looks pretty good to me. Pity about that bug back in c9548f6!
Didn't know that EPICS had its own at exit framework; in fact, didn't know that EPICS handled exit at all now (apart from pulling the plug, like we always used to).
|
|
||
| epicsExit = Com.epicsExit | ||
| epicsExit.argtypes = () | ||
| epicsExit.argtypes = (c_int,) |
There was a problem hiding this comment.
Oops.
Looks like this was my mistake, back in commit c9548f6
| epicsExit() | ||
|
|
||
| elif hasattr(atexit, '_run_exitfuncs'): # py 3.x | ||
| atexit._run_exitfuncs() |
There was a problem hiding this comment.
Do we need to do the same dance as above with sys.exitfunc to make sure we don't get multiple executions of exit handlers?
There was a problem hiding this comment.
Not as I read it. _run_exitfuncs() (like epicsExitCallAtExits()) removes callbacks which have run.
| def __repr__(self): # hack to exit when "called" with no parenthesis | ||
| sys.exit(0) | ||
| def __call__(self, code=0): | ||
| sys.exit(code) |
There was a problem hiding this comment.
Why aren't we calling epicsExit here anymore?
There was a problem hiding this comment.
I'm guessing you answered this above in #35 (comment)
|
@thomascobb, did I accidentally just delete one of your comments? I see a message to that effect upstream! |
This has been around for quite some time. It's worth noting that there are some platform specific differences.
|
epicsExit(int)to avoid exit with ~random code.atexit._run_exitfuncs()with py 3.xinteractive_ioc(call_exit=False)