Concurrency bug in channel access to local DB

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

Bug Description

dbContextReadNotifyCache::callReadNotify allocates a single buffer to hold the value data it retrieves from the database. It then releases its mutex and issues the callback. This means that another thread can overwrite the data. There is no way for a caller to protect against this short of serializing all calls to ca_array_get_callback. This breaks state machine code quite badly.

Additional information:
The bug is easily fixed by allocating and freeing this data buffer on each call.

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

Tags: ca 3.14
Revision history for this message
Jeff Hill (johill-lanl) wrote :
Download full text (9.6 KiB)

I commited this fix

cvs diff: Diffing .
Index: dbCAC.h
===================================================================
RCS file: /net/phoebus/epicsmgr/cvsroot/epics/base/src/db/dbCAC.h,v
retrieving revision 1.39.2.5
diff -c -r1.39.2.5 dbCAC.h
*** dbCAC.h 23 Jan 2004 20:15:35 -0000 1.39.2.5
--- dbCAC.h 12 Apr 2005 16:38:59 -0000
***************
*** 126,145 ****
   dbContextPrivateListOfIO & operator = ( const dbContextPrivateListOfIO & );
  };

! // allow only one thread at a time to use the cache, but do not hold
! // lock when calling the callback
  class dbContextReadNotifyCache {
  public:
      dbContextReadNotifyCache ( epicsMutex & );
- ~dbContextReadNotifyCache ();
      void callReadNotify ( epicsGuard < epicsMutex > &,
          struct dbAddr & addr, unsigned type, unsigned long count,
              cacReadNotify & notify );
      void show ( epicsGuard < epicsMutex > &, unsigned level ) const;
  private:
! unsigned long readNotifyCacheSize;
! epicsMutex & mutex;
! char * pReadNotifyCache;
   dbContextReadNotifyCache ( const dbContextReadNotifyCache & );
   dbContextReadNotifyCache & operator = ( const dbContextReadNotifyCache & );
  };
--- 126,159 ----
   dbContextPrivateListOfIO & operator = ( const dbContextPrivateListOfIO & );
  };

! class dbContextReadNotifyCacheAllocator {
! public:
! dbContextReadNotifyCacheAllocator ();
! ~dbContextReadNotifyCacheAllocator ();
! char * alloc ( unsigned long size );
! void free ( char * pFree );
! void show ( unsigned level ) const;
! private:
! struct cacheElem_t {
! struct cacheElem_t * pNext;
! };
! unsigned long _readNotifyCacheSize;
! cacheElem_t * _pReadNotifyCache;
! void reclaimAllCacheEntries ();
! dbContextReadNotifyCacheAllocator ( const dbContextReadNotifyCacheAllocator & );
! dbContextReadNotifyCacheAllocator & operator = ( const dbContextReadNotifyCacheAllocator & );
! };
!
  class dbContextReadNotifyCache {
  public:
      dbContextReadNotifyCache ( epicsMutex & );
      void callReadNotify ( epicsGuard < epicsMutex > &,
          struct dbAddr & addr, unsigned type, unsigned long count,
              cacReadNotify & notify );
      void show ( epicsGuard < epicsMutex > &, unsigned level ) const;
  private:
! dbContextReadNotifyCacheAllocator _allocator;
! epicsMutex & _mutex;
   dbContextReadNotifyCache ( const dbContextReadNotifyCache & );
   dbContextReadNotifyCache & operator = ( const dbContextReadNotifyCache & );
  };
Index: dbContextReadNotifyCache.cpp
===================================================================
RCS file: /net/phoebus/epicsmgr/cvsroot/epics/base/src/db/dbContextReadNotifyCache.cpp,v
retrieving revision 1.1.2.1
diff -c -r1.1.2.1 dbContextReadNotifyCache.cpp
*** dbContextReadNotifyCache.cpp 9 Jan 2004 00:42:13 -0000 1.1.2.1
--- dbContextReadNotifyCache.cpp 12 Apr 2005 16:52:08 -0000
***************
*** 14,20 ****
   */

  #include "epicsMutex.h"
- #include "tsFreeList.h"

  #include "cadef.h" // this can be eliminated when the callbacks use the new interface
  #include "db_access.h" // should be eliminated here in the future
--- 14,19 ----
***************
...

Read more...

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

ran CA regression tests against a local db channel

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

fixed in R3.14.8

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

PS: allocating and freeing on every call would probably introduce unacceptable
overhead so a buffer pool was implemented.

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

fixed in R3.14.8

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

R3.14.8 Release.

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.