segfault in ca_attach_context() during exits

Bug #1743076 reported by Andrew Johnson on 2018-01-13
This bug affects 1 person
Affects Status Importance Assigned to Milestone
Status tracked in 7.0
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 epicsThreadPrivateId that stores the current CA client context, resulting in a segfault.

A program demonstrating this is attached. The back-trace from the crash looks as follows on my Linux laptop, note the zero parameter to epicsThreadPrivateGet():

Program received signal SIGSEGV, Segmentation fault.
epicsThreadPrivateGet (id=0x0)
    at ../../../src/libCom/osi/os/posix/osdThread.c:857
857 return pthread_getspecific(*key);
(gdb) bt
#0 epicsThreadPrivateGet (id=0x0)
    at ../../../src/libCom/osi/os/posix/osdThread.c:857
#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 epicsExitCallAtExitsPvt (pep=<optimized out>)
    at ../../../src/libCom/misc/epicsExit.c:80
#4 epicsExitCallAtExits () at ../../../src/libCom/misc/epicsExit.c:97
#5 0x00007ffff758753a in __cxa_finalize (d=0x7ffff7b6e120)
    at cxa_finalize.c:56
#6 0x00007ffff79339d3 in __do_global_dtors_aux ()
   from /home/anj/Software/epics/base-3.14/lib/linux-x86_64/
#7 0x00007fffffffde40 in ?? ()
#8 0x00007ffff7dea8da in _dl_fini () at dl-fini.c:252
Backtrace stopped: frame did not save the PC

Andrew Johnson (anj) wrote :
Andrew Johnson (anj) wrote :

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
--- a/src/ca/client/access.cpp
+++ b/src/ca/client/access.cpp
@@ -127,21 +127,10 @@ const char * ca_message_text []

 static epicsThreadOnceId caClientContextIdOnce = EPICS_THREAD_ONCE_INIT;

-extern "C" void ca_client_exit_handler (void *)
- if ( caClientContextId ) {
- epicsThreadPrivateDelete ( caClientContextId );
- caClientContextId = 0;
- }
 // runs once only for each process
 extern "C" void ca_init_client_context ( void * )
     caClientContextId = epicsThreadPrivateCreate ();
- if ( caClientContextId ) {
- epicsAtExit ( ca_client_exit_handler,0 );
- }


mdavidsaver (mdavidsaver) wrote :

I don't have any objection to this change.

Ralph Lange (ralph-lange) wrote :

Looks fine.

To post a comment you must log in.
This report contains Public information  Edit
Everyone can see this information.

Other bug subscribers