Hi folks!
Right now, soft IOCs running on general purpose OSs can be terminated
using synchronous mechanisms (e.g. exit in iocsh or Restart PV from
IOCStats), or asynchronous mechanisms (usually signals, either from
procServ, systemd, or a container runtime). For synchronous termination,
epicsExit is run, and executes functions registered with epicsAtExit;
this means that drivers which have cleanup requirements (usually
removing some file or relinquishing some handle) can register those
cleanup routines, and they run during synchronous termination. [1]
mentions such a need, and I know that when using ADAravis, it's best to
relinquish write-access to a camera before exiting (though that isn't
done right now IIRC), otherwise it's necessary to wait for it to
timeout; I have also observed this pattern on some internal device drivers.
[1] https://epics.anl.gov/tech-talk/2009/msg01000.php
This creates a problem for driver developers which want to cover all
cases, because not only do they need to register cleanup functions with
epicsAtExit, but also add signal handlers (which means that they now
"own" that signal handler, which also creates problems if we wish to
have more than one device driver on a single IOC). They must also
implement these signal handlers safely: very few functions are
async-safe and can be executed in a signal handler, and epicsExit
definitely isn't; so their signal handlers should basically only trigger
an event or set a flag that their normal program flow can handle
synchronously in order to then call epicsExit. If they implement signal
handling in such a manner, they have the advantage that they only need
to call epicsExit, because their atExit functions will be already be called.
Given this scenario, I would like to propose adding a function to
epics-base which launches a thread listening to an exitEvent before
calling epicsExit, and registers a signal handler to trigger this event.
I have attached an initial implementation, which implements the function
below. It only launches the thread if a signal handler is registered, so
users don't have to pay the cost if it's not needed.
/** Registers a signal handler to safely exit the application using
epicsExit()
* when the signal identified by signum is received. Returns 0 on
success. */
int epicsExitOnSignal(int signum);
One option would be to allow driver support code to call
epicsExitOnSignal, but I don't think drivers actually know what sort of
signal a program may receive (there are many ways to launch and stop
IOCs, after all). Another option, which I prefer over the previous one,
would be to add an iocsh function, which can simply be called in the
relevant startup scripts. Alternatively, signal handlers could be
registered for all relevant signals (SIGTERM, SIGINT?) by default, and
an iocsh function or variable could exist to disable this functionality.
I am comfortable with suggesting this mechanism as a default
functionality because it runs epicsExit on a thread that's out of
control of device drivers, which is exactly the same thing that happens
when one runs "exit" in iocsh, so all drivers should already be ready
for such situations.
In summary, this change would simplify the implementation of cleanup
code, and avoid footguns with signal handling, by having a single path
for process termination; and it would do so using the same program flow
as the battle-tested exit command from iocsh. I don't understand process
lifecycles on Windows, and that's not addressed by this proposal at all.
I don't know if it only makes sense to expose this functionality on
POSIX, or if it could somehow be shared.
I would love to hear your thoughts on this idea, if it fits inside
epics-base, and opinions on how it should be used (by driver developers,
by users in startup scripts, or by default).
Cheers,
Érico
Aviso Legal: Esta mensagem e seus anexos podem conter informações confidenciais e/ou de uso restrito. Observe atentamente seu conteúdo e considere eventual consulta ao remetente antes de copiá-la, divulgá-la ou distribuí-la. Se você recebeu esta mensagem por engano, por favor avise o remetente e apague-a imediatamente.
Disclaimer: This email and its attachments may contain confidential and/or privileged information. Observe its content carefully and consider possible querying to the sender before copying, disclosing or distributing it. If you have received this email by mistake, please notify the sender and delete it immediately.
#include <signal.h>
#include <epicsEvent.h>
#include <epicsExit.h>
#include <epicsStdio.h>
#include <epicsThread.h>
#include <epicsExport.h>
class epicsSignalExit: epicsThreadRunable {
epicsEvent exitEvent;
epicsThread thread;
void run() override;
epicsSignalExit();
public:
void trigger();
static epicsSignalExit *getInstance();
};
/* priority must be high, at this point we want the application to exit */
epicsSignalExit::epicsSignalExit():
thread(*this, "signalExit", epicsThreadStackMedium, epicsThreadPriorityHigh)
{
thread.start();
}
void epicsSignalExit::run()
{
exitEvent.wait();
fprintf(stderr, "signal received, calling epicsExit...\n");
epicsExit(0);
}
void epicsSignalExit::trigger()
{
exitEvent.trigger();
}
epicsSignalExit *epicsSignalExit::getInstance()
{
static epicsSignalExit signalExit{};
return &signalExit;
}
static void epicsSignalExitHandler(int signum)
{
epicsSignalExit::getInstance()->trigger();
}
int epicsExitOnSignal(int signum)
{
/* make sure the signalExit object is created */
epicsSignalExit::getInstance();
return signal(signum, epicsSignalExitHandler) == SIG_ERR;
}
- Replies:
- Re: RFC: add a mechanism to call epicsExit when signals are received Michael Davidsaver via Tech-talk
- Re: RFC: add a mechanism to call epicsExit when signals are received Ralph Lange via Tech-talk
- Navigate by Date:
- Prev:
Stream2 support in ADEiger Mark Rivers via Tech-talk
- Next:
Re: RFC: add a mechanism to call epicsExit when signals are received Michael Davidsaver via Tech-talk
- Index:
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
<2025>
- Navigate by Thread:
- Prev:
Re: Stream2 support in ADEiger Yendell, Gary (DLSLtd, RAL, LSCI) via Tech-talk
- Next:
Re: RFC: add a mechanism to call epicsExit when signals are received Michael Davidsaver via Tech-talk
- Index:
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
<2025>
|