Subject: |
Re: Proglem doing CA calls after catching a signal |
From: |
Robert Soliday <[email protected]> |
To: |
tech-talk <[email protected]> |
Date: |
Mon, 26 Jul 2004 13:58:44 -0500 |
Here is what I have implemented to try to side step the whole problem of
calling CA calls in a signal handler. Basically I have a global variable
that is set to 1 on a SIGINT, SIGTERM, or SIGQUIT signal. I have a
special version of ca_pend_event that looks at this flag every second.
At certain points in the code, such as after my ca_pend_events, I can
exit out if the flag has been set. This results in a reasonably
responsiveness to a Control-C. The result is the exit handler is called
from the main thread and there are no CA issues. If the code is hanging
up in a different section, such as a ca_pend_io, the user can do a
second Control-C to force an exit. In this case it attempts to connect
to the ca_current_context in the exit handler. If it can't (rarely seen)
it will not try to do any CA calls. Also once it enters the exit handler
I send any additional signals to a dummy signal handler so that it does
not attempt to exit while I am in the exit handler.
--Bob Soliday
_________________________________
int sigint=0;
int main(int argc, char **argv) {
...
#ifdef EPICS313
ca_task_initialize();
#else
if (ca_context_create(ca_enable_preemptive_callback)!=ECA_NORMAL) {
fprintf(stderr, "Unable to initiate channel access context\n");
return(1);
}
#endif
...
signal(SIGINT, sigint_interrupt_handler);
signal(SIGTERM, sigint_interrupt_handler);
signal(SIGILL, interrupt_handler);
signal(SIGABRT, interrupt_handler);
signal(SIGFPE, interrupt_handler);
signal(SIGSEGV, interrupt_handler);
#ifndef _WIN32
signal(SIGHUP, interrupt_handler);
signal(SIGQUIT, sigint_interrupt_handler);
signal(SIGTRAP, interrupt_handler);
signal(SIGBUS, interrupt_handler);
#endif
atexit( rc_interrupt_handler );
...
oag_ca_pend_event(10, &sigint);
}
/* wrapper for ca_pend_event that allows breaking out early if the
flag is set from a signal handler. Unlike ca_pend_event, a timeout
of zero will not be converted to infinity. */
long oag_ca_pend_event(double timeout, int *flag) {
long status=ECA_NORMAL;
if (timeout <= 0)
ca_poll();
while (timeout > 0) {
if (*flag)
return(status);
if (timeout > 1) {
status = ca_pend_event(1);
timeout -= 1;
} else {
status = ca_pend_event(timeout);
timeout = 0;
}
}
return(status);
}
void sigint_interrupt_handler(int sig) {
sigint=1;
signal(SIGINT,interrupt_handler);
signal(SIGTERM,interrupt_handler);
#ifndef _WIN32
signal(SIGQUIT,interrupt_handler);
#endif
}
void interrupt_handler(int sig) {
exit(1);
}
void dummy_interrupt_handler(int sig) {
}
void rc_interrupt_handler() {
int ca=1;
signal(SIGINT, dummy_interrupt_handler);
signal(SIGTERM, dummy_interrupt_handler);
#ifndef _WIN32
signal(SIGQUIT, dummy_interrupt_handler);
#endif
#ifndef EPICS313
if (ca_current_context() == NULL)
ca=0;
if (ca)
ca_attach_context(ca_current_context());
#endif
if (ca) {
...
ca_task_exit();
}
}
Chris Larrieu wrote:
Isn't the crux of the problem that there's no way to specify/predict
which thread should handle a signal?
Till Straumann wrote:
Eric Norum wrote:
Robert Soliday wrote:
After upgrading to Epics/Base 3.14.6 from 3.13.10 I am having
difficulty handling signals. In one of our applications if the user
does a control-C it is suppose to trap the signal and restore the
PVs to their original values. Odds are the control-c will occur
while in a ca_pend_event call. When I go to do a ca_pend_io in the
interrupt handler I get the error:
pthread_mutex_unlock failed: error Not owner
fatal error: epicsMutexOsdUnlock
I have included a simple program that displays the same problem. If
anyone knows the proper way of doing CA calls after catching a
signal please let me know.
I was wondering when we'd have to address the grotty details of POSIX
thread/signal interaction. As a first pass, perhaps we should have
epicsThreadCreate call sigprocmask to block signals in all but the
main (startup) thread? (assuming, of course, that sigprocmask
applies on a thread-by-thread basis?
Can you use something other than signals to do this? For example,
could you move the work to another thread and have the interactive
thread wait for a return to be typed and then use epicsEventSignal or
something like that to communicate between the threads?
My guess is that trying to make EPICS robust in the face of signals
is going to uncover lots of problems in the thread/signal support of
the various platforms we're now supporting.
Good guess. I had a taste of this when making labCa (matlab/scilab - CA
interface) calls Ctrl-C interruptible. Just dealing with three platforms
(linux, solaris and win32) reveals that the details of all of those are
very different and a pain to deal with.
Till
- Replies:
- Re: Proglem doing CA calls after catching a signal Eric Norum
- References:
- Proglem doing CA calls after catching a signal Robert Soliday
- Re: Proglem doing CA calls after catching a signal Eric Norum
- Re: Proglem doing CA calls after catching a signal Till Straumann
- Re: Proglem doing CA calls after catching a signal Chris Larrieu
- Navigate by Date:
- Prev:
Re: Proglem doing CA calls after catching a signal Eric Norum
- Next:
Re: Proglem doing CA calls after catching a signal Eric Norum
- 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
- Navigate by Thread:
- Prev:
Re: Proglem doing CA calls after catching a signal Eric Norum
- Next:
Re: Proglem doing CA calls after catching a signal Eric Norum
- 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
|