Skip to content

Commit 4bbc933

Browse files
Xavier GOIZIOUAraneidae
authored andcommitted
Add non_interactive_ioc() function
Resolves PR #156
1 parent 4388c69 commit 4bbc933

File tree

5 files changed

+31
-0
lines changed

5 files changed

+31
-0
lines changed

CHANGELOG.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ Unreleased_
1111
-----------
1212

1313
Added:
14+
1415
- `Enable setting alarm status of Out records <../../pull/157>`_
16+
- `Adding the non_interactive_ioc function <../../pull/156>`_
1517

1618
Removed:
1719

docs/reference/api.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,12 @@ Test Facilities`_ documentation for more details of each function.
120120
.. autofunction:: generalTimeReport
121121
.. autofunction:: eltc
122122

123+
.. autofunction:: non_interactive_ioc
124+
125+
When used with a service manager, use python's -u option or the environment
126+
variable PYTHONUNBUFFERED=TRUE. This ensures that python output, i.e. stdout
127+
and stderr streams, is sent directly to the terminal.
128+
123129
.. attribute:: exit
124130

125131
Displaying this value will invoke ``epicsExit()`` causing the IOC to

softioc/asyncio_dispatcher.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import logging
44
import threading
55
import atexit
6+
import signal
67

78
class AsyncioDispatcher:
89
def __init__(self, loop=None, debug=False):
@@ -48,6 +49,17 @@ def close(self):
4849

4950
self.__shutdown()
5051

52+
def wait_for_quit(self):
53+
stop_event = threading.Event()
54+
55+
def signal_handler(signum, frame):
56+
stop_event.set()
57+
58+
signal.signal(signal.SIGINT, signal_handler)
59+
signal.signal(signal.SIGTERM, signal_handler)
60+
61+
stop_event.wait()
62+
5163
async def __inloop(self, started):
5264
self.loop = asyncio.get_running_loop()
5365
self.__interrupt = asyncio.Event()

softioc/cothread_dispatcher.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ def __init__(self, dispatcher = None):
1919
else:
2020
self.__dispatcher = dispatcher
2121

22+
self.wait_for_quit = cothread.WaitForQuit
23+
2224
def __call__(
2325
self,
2426
func,

softioc/softioc.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,3 +352,12 @@ def interactive_ioc(context = {}, call_exit = True):
352352

353353
if call_exit:
354354
safeEpicsExit(0)
355+
356+
357+
def non_interactive_ioc():
358+
'''Function to run the IOC in non-interactive mode. This mode is useful for
359+
running the IOC as a background process without user interaction.
360+
This function expects a stop signal. When it receives one, the IOC stops.
361+
'''
362+
device.dispatcher.wait_for_quit()
363+
safeEpicsExit(0)

0 commit comments

Comments
 (0)