segfault in ca_attach_context() during exits
Affects | Status | Importance | Assigned to | Milestone | ||
---|---|---|---|---|---|---|
EPICS Base | Status tracked in 7.0 | |||||
3.14 |
Fix Released
|
Undecided
|
Unassigned | |||
3.15 |
Fix Released
|
Undecided
|
Unassigned | |||
3.16 |
Fix Released
|
Undecided
|
Unassigned | |||
7.0 |
Fix Released
|
Low
|
Andrew Johnson |
Bug Description
If ca_attach_context() is called inside an epicsAtExit() routine that was registered before the CA client library was initialized (i.e. before any CA routine was called), one of the CA library's two epicsAtExit() routines will have deleted and zeroed the epicsThreadPriv
A program demonstrating this is attached. The back-trace from the crash looks as follows on my Linux laptop, note the zero parameter to epicsThreadPriv
Program received signal SIGSEGV, Segmentation fault.
epicsThreadPriv
at ../../.
857 return pthread_
(gdb) bt
#0 epicsThreadPriv
at ../../.
#1 0x00007ffff7b9e718 in ca_attach_context (pCtx=0x604b60)
at ../access.cpp:761
#2 0x00000000004009d4 in contexit (junk=<optimized out>) at ../caBug.c:12
#3 0x00007ffff79450b7 in epicsExitCallAt
at ../../.
#4 epicsExitCallAt
#5 0x00007ffff758753a in __cxa_finalize (d=0x7ffff7b6e120)
at cxa_finalize.c:56
#6 0x00007ffff79339d3 in __do_global_
from /home/anj/
#7 0x00007fffffffde40 in ?? ()
#8 0x00007ffff7dea8da in _dl_fini () at dl-fini.c:252
Backtrace stopped: frame did not save the PC
The CA client library contains 2 atexit handlers, one of which deletes the caClientContextId thread-variable (and sets the Id to 0). There seems no real need for this thread variable to ever be deleted, the ca_init_ client_ context( ) routine shown below is protected by an epicsThreadOnce variable so it can only ever be called once. I propose the following change, which removes that exit handler and stops the segfault:
diff --git a/src/ca/ client/ access. cpp b/src/ca/ client/ access. cpp client/ access. cpp client/ access. cpp
--- a/src/ca/
+++ b/src/ca/
@@ -127,21 +127,10 @@ const char * ca_message_text []
static epicsThreadOnceId caClientContext IdOnce = EPICS_THREAD_ ONCE_INIT;
-extern "C" void ca_client_ exit_handler (void *) ateDelete ( caClientContextId ); client_ context ( void * ) ntextId = epicsThreadPriv ateCreate (); exit_handler, 0 );
-{
- if ( caClientContextId ) {
- epicsThreadPriv
- caClientContextId = 0;
- }
-}
-
// runs once only for each process
extern "C" void ca_init_
{
caClientCo
- if ( caClientContextId ) {
- epicsAtExit ( ca_client_
- }
}
/*