SEGV calling ca_context_create from file scope constructor

Bug #541274 reported by Jeff Hill
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
EPICS Base
Fix Released
High
Andrew Johnson

Bug Description

From Margaret Votava,

We are trying to understand a problem with a DESY/DOOCS utility. It generates a segmentation fault within ca_task_initialize (stack trace below). The

epicsMutex ca_client_context::defaultServiceInstallMutex;

constructor is not being called in all OS platform/Compiler combinations.

In particular, a failing combination is
Linux 2.6.8-22.0.2/gcc v3.4.3 (red hat)
Linux 2.6.1/gcc v3.2.3 (red hat)

but works in Solaris with Solaris compiler.

We believe that this is a linker problem.

Has anyone seen before or have any clues of how to fix?

Thank you kindly,
Margaret

### epics code ###

(gdb) where
#0 epicsMutexLock (pmutexNode=0x0)
    at ../../../src/libCom/osi/epicsMutex.cpp:118
#1 0x006add15 in epicsMutex::lock (this=0x0)
    at ../../../src/libCom/osi/epicsMutex.cpp:211
#2 0x00ca19cb in ca_client_context (this=0x8d8ce08,
    enablePreemptiveCallback=false) at ../../../include/epicsGuard.h:68 #3 0x00c88305 in ca_context_create (
    premptiveCallbackSelect=ca_disable_preemptive_callback)
    at ../access.cpp:204
#4 0x00c8835e in ca_task_initialize () at ../access.cpp:180

### doocs code ####

#5 0x00a3e9f5 in epics_init ()
    at
/home/votava/smtf/doocs/libs/clientlib/source/clientlib/eq_svr.cc:1928
#6 0x00a464b5 in EqCall (this=0x8d8cc88)
    at
/home/votava/smtf/doocs/libs/clientlib/source/clientlib/eq_client.cc:369
#7 0x00e05837 in __static_initialization_and_destruction_0
(__initialize_p=1,
    __priority=65535)
    at
/home/votava/smtf/doocs/libs/dddlib/source/dddlib/panels/device_attr_stubs.cc:26
#8 0x00e05917 in global constructors keyed to ea ()
    at
/home/votava/smtf/doocs/libs/dddlib/source/dddlib/panels/device_attr_stubs.cc:400
#9 0x00e36819 in __do_global_ctors_aux ()
   from
/home/votava/smtf/doocs/ups/../ups/../libs/dddlib/ups/../ups/../Linux/lib/libddd.so.2.2.5
#10 0x00d45add in _init ()
   from
/home/votava/smtf/doocs/ups/../ups/../libs/dddlib/ups/../ups/../Linux/lib/libddd.so.2.2.5
#11 0x00271318 in _dl_init_internal () from /lib/ld-linux.so.2 #12 0x002657ff in _dl_start_user () from /lib/ld-linux.so.2

Additional information:

The issue you have discovered occurs only when calling ca_context_create (a.k.a. ca_task_initialize) from your C++ file scope object's constructor.

The static variable "ca_client_context::defaultServiceInstallMutex" is also file scope, and this implies that it's constructor along with the constructor of your device_attr_stubs both run before main() is called.

Which file scope constructor runs first is very C++ compiler implementation dependent.

Let me know if the attached patch resolves your troubles.

Jeff

cvs diff -u -wb -i -- ca_client_context.cpp oldAccess.h (in directory D:\users\hill\R3.14.dll_hell_fix\epics\base\src\ca\)
Index: ca_client_context.cpp
===================================================================
RCS file: /net/phoebus/epicsmgr/cvsroot/epics/base/src/ca/ca_client_context.cpp,v
retrieving revision 1.9.2.18
diff -c -u -w -b -i -r1.9.2.18 ca_client_context.cpp
cvs diff: conflicting specifications of output style
--- ca_client_context.cpp 13 Apr 2005 17:28:13 -0000 1.9.2.18
+++ ca_client_context.cpp 17 Feb 2006 22:22:11 -0000
@@ -47,6 +47,7 @@
 {
     epicsThreadPrivateDelete ( caClientCallbackThreadId );
     caClientCallbackThreadId = 0;
+ delete ca_client_context::pDefaultServiceInstallMutex;
 }

 // runs once only for each process
@@ -54,13 +55,14 @@
 {
     caClientCallbackThreadId = epicsThreadPrivateCreate ();
     assert ( caClientCallbackThreadId );
+ ca_client_context::pDefaultServiceInstallMutex = new epicsMutex;
     epicsAtExit ( cacExitHandler,0 );
 }

 extern epicsThreadPrivateId caClientContextId;

 cacService * ca_client_context::pDefaultService = 0;
-epicsMutex ca_client_context::defaultServiceInstallMutex;
+epicsMutex * ca_client_context::pDefaultServiceInstallMutex;

 ca_client_context::ca_client_context ( bool enablePreemptiveCallback ) :
     ca_exception_func ( 0 ), ca_exception_arg ( 0 ),
@@ -77,9 +79,7 @@

     epicsThreadOnce ( & cacOnce, cacOnceFunc, 0 );

- {
- // this wont consistently work if called from file scope constructor
- epicsGuard < epicsMutex > guard ( ca_client_context::defaultServiceInstallMutex );
+ epicsGuard < epicsMutex > guard ( *ca_client_context::pDefaultServiceInstallMutex );
         if ( ca_client_context::pDefaultService ) {
             this->pServiceContext.reset (
                 & ca_client_context::pDefaultService->contextCreate (
@@ -88,7 +88,6 @@
         else {
             this->pServiceContext.reset ( new cac ( this->mutex, this->cbMutex, *this ) );
         }
- }

     this->sock = epicsSocketCreate ( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
     if ( this->sock == INVALID_SOCKET ) {
@@ -734,8 +733,9 @@

 void ca_client_context::installDefaultService ( cacService & service )
 {
- // this wont consistently work if called from file scope constructor
- epicsGuard < epicsMutex > guard ( ca_client_context::defaultServiceInstallMutex );
+ epicsThreadOnce ( & cacOnce, cacOnceFunc, 0 );
+
+ epicsGuard < epicsMutex > guard ( *ca_client_context::pDefaultServiceInstallMutex );
     if ( ca_client_context::pDefaultService ) {
         throw std::logic_error
             ( "CA in-memory service already installed and can't be replaced");
Index: oldAccess.h
===================================================================
RCS file: /net/phoebus/epicsmgr/cvsroot/epics/base/src/ca/oldAccess.h,v
retrieving revision 1.47.2.14
diff -c -u -w -b -i -r1.47.2.14 oldAccess.h
cvs diff: conflicting specifications of output style
--- oldAccess.h 19 Oct 2004 20:48:51 -0000 1.47.2.14
+++ oldAccess.h 17 Feb 2006 22:07:21 -0000
@@ -286,6 +286,9 @@
     void operator delete ( void * );
 };

+extern "C" void cacOnceFunc ( void * );
+extern "C" void cacExitHandler ( void *);
+
 struct ca_client_context : public cacContextNotify
 {
 public:
@@ -412,8 +415,10 @@
  ca_client_context ( const ca_client_context & );
  ca_client_context & operator = ( const ca_client_context & );

+ friend void cacOnceFunc ( void * );
+ friend void cacExitHandler ( void *);
     static cacService * pDefaultService;
- static epicsMutex defaultServiceInstallMutex;
+ static epicsMutex * pDefaultServiceInstallMutex;
 };

 int fetchClientContext ( ca_client_context * * ppcac );

Original Mantis Bug: mantis-239
    http://www.aps.anl.gov/epics/mantis/view_bug_page.php?f_id=239

Tags: ca 3.14
Revision history for this message
Jeff Hill (johill-lanl) wrote :

I susequently installed this patch to reduce the scope of the previously mentioned patch.

Saved settings for D:\users\hill\R3.14.dll_hell_fix\epics\base successfully...
cvs diff -u -wb -i -- ca_client_context.cpp (in directory D:\users\hill\R3.14.dll_hell_fix\epics\base\src\ca\)
Index: ca_client_context.cpp
===================================================================
RCS file: /net/phoebus/epicsmgr/cvsroot/epics/base/src/ca/ca_client_context.cpp,v
retrieving revision 1.9.2.19
diff -c -u -w -b -i -r1.9.2.19 ca_client_context.cpp
cvs diff: conflicting specifications of output style
--- ca_client_context.cpp 17 Feb 2006 22:31:42 -0000 1.9.2.19
+++ ca_client_context.cpp 17 Feb 2006 22:38:36 -0000
@@ -78,7 +78,7 @@
     }

     epicsThreadOnce ( & cacOnce, cacOnceFunc, 0 );
-
+ {
     epicsGuard < epicsMutex > guard ( *ca_client_context::pDefaultServiceInstallMutex );
     if ( ca_client_context::pDefaultService ) {
         this->pServiceContext.reset (
@@ -88,6 +88,7 @@
     else {
         this->pServiceContext.reset ( new cac ( this->mutex, this->cbMutex, *this ) );
     }
+ }

     this->sock = epicsSocketCreate ( AF_INET, SOCK_DGRAM, IPPROTO_UDP );
     if ( this->sock == INVALID_SOCKET ) {

***** CVS exited normally with code 1 *****

Revision history for this message
Andrew Johnson (anj) wrote :

Patch included in R3.14.9.

Revision history for this message
Andrew Johnson (anj) wrote :

R3.14.9 Released.

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

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.