Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Enhance mutex initialization to prevent possible race conditions between sqlite3_initialize() and sqlite3_config(). Also, re-check sqlite3GlobalConfig.isInit after the mutex subsystem has been initialized. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | mutexInitCmpSwap |
Files: | files | file ages | folders |
SHA1: |
f6a8f577957769171acd72df3cc9aa5a |
User & Date: | mistachkin 2015-09-11 05:06:15.636 |
Context
2015-09-11
| ||
23:24 | Make sure that the mutex implementation can be altered after calling sqlite3_shutdown(). (check-in: dc2cf89743 user: mistachkin tags: mutexInitCmpSwap) | |
05:06 | Enhance mutex initialization to prevent possible race conditions between sqlite3_initialize() and sqlite3_config(). Also, re-check sqlite3GlobalConfig.isInit after the mutex subsystem has been initialized. (check-in: f6a8f57795 user: mistachkin tags: mutexInitCmpSwap) | |
01:22 | Updates to the sqlite3_value_subtype() and sqlite3_result_subtype() documentation and to test cases for json1 dealing with those interfaces. (check-in: d6cadbe9fe user: drh tags: trunk) | |
Changes
Changes to src/global.c.
︙ | ︙ | |||
170 171 172 173 174 175 176 177 178 179 180 181 182 183 | SQLITE_USE_URI, /* bOpenUri */ SQLITE_ALLOW_COVERING_INDEX_SCAN, /* bUseCis */ 0x7ffffffe, /* mxStrlen */ 0, /* neverCorrupt */ 128, /* szLookaside */ 500, /* nLookaside */ {0,0,0,0,0,0,0,0}, /* m */ {0,0,0,0,0,0,0,0,0}, /* mutex */ {0,0,0,0,0,0,0,0,0,0,0,0,0},/* pcache2 */ (void*)0, /* pHeap */ 0, /* nHeap */ 0, 0, /* mnHeap, mxHeap */ SQLITE_DEFAULT_MMAP_SIZE, /* szMmap */ SQLITE_MAX_MMAP_SIZE, /* mxMmap */ | > | 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 | SQLITE_USE_URI, /* bOpenUri */ SQLITE_ALLOW_COVERING_INDEX_SCAN, /* bUseCis */ 0x7ffffffe, /* mxStrlen */ 0, /* neverCorrupt */ 128, /* szLookaside */ 500, /* nLookaside */ {0,0,0,0,0,0,0,0}, /* m */ (void*)0, /* pMutex */ {0,0,0,0,0,0,0,0,0}, /* mutex */ {0,0,0,0,0,0,0,0,0,0,0,0,0},/* pcache2 */ (void*)0, /* pHeap */ 0, /* nHeap */ 0, 0, /* mnHeap, mxHeap */ SQLITE_DEFAULT_MMAP_SIZE, /* szMmap */ SQLITE_MAX_MMAP_SIZE, /* mxMmap */ |
︙ | ︙ |
Changes to src/main.c.
︙ | ︙ | |||
167 168 169 170 171 172 173 | ** This operation is protected by the STATIC_MASTER mutex. Note that ** MutexAlloc() is called for a static mutex prior to initializing the ** malloc subsystem - this implies that the allocation of a static ** mutex must not require support from the malloc subsystem. */ MUTEX_LOGIC( pMaster = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); ) sqlite3_mutex_enter(pMaster); | > > > > > > | | 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 | ** This operation is protected by the STATIC_MASTER mutex. Note that ** MutexAlloc() is called for a static mutex prior to initializing the ** malloc subsystem - this implies that the allocation of a static ** mutex must not require support from the malloc subsystem. */ MUTEX_LOGIC( pMaster = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); ) sqlite3_mutex_enter(pMaster); if( sqlite3GlobalConfig.isInit ){ assert( sqlite3GlobalConfig.isMutexInit ); assert( sqlite3GlobalConfig.isMallocInit ); sqlite3_mutex_leave(pMaster); return SQLITE_OK; } sqlite3GlobalConfig.isMutexInit = 1; /* possibly redundant */ if( !sqlite3GlobalConfig.isMallocInit ){ rc = sqlite3MallocInit(); } if( rc==SQLITE_OK ){ sqlite3GlobalConfig.isMallocInit = 1; if( !sqlite3GlobalConfig.pInitMutex ){ sqlite3GlobalConfig.pInitMutex = |
︙ | ︙ | |||
380 381 382 383 384 385 386 | sqlite3GlobalConfig.bCoreMutex = 1; /* Enable mutex on core */ sqlite3GlobalConfig.bFullMutex = 1; /* Enable mutex on connections */ break; } #endif #if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0 /* IMP: R-63666-48755 */ case SQLITE_CONFIG_MUTEX: { | > > > > | | > > > | 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 | sqlite3GlobalConfig.bCoreMutex = 1; /* Enable mutex on core */ sqlite3GlobalConfig.bFullMutex = 1; /* Enable mutex on connections */ break; } #endif #if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0 /* IMP: R-63666-48755 */ case SQLITE_CONFIG_MUTEX: { /* Atomically compare-and-swap the mutex implementation pointer to * help prevent a race condition with sqlite3MutexInit(). */ if( sqlite3CompareAndSwap((void * volatile *)&sqlite3GlobalConfig.pMutex, 0, &sqlite3GlobalConfig.mutex)==0 ){ /* Specify an alternative mutex implementation */ sqlite3GlobalConfig.mutex = *va_arg(ap, sqlite3_mutex_methods*); }else{ rc = SQLITE_ERROR; } break; } #endif #if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0 /* IMP: R-14450-37597 */ case SQLITE_CONFIG_GETMUTEX: { /* Retrieve the current mutex implementation */ *va_arg(ap, sqlite3_mutex_methods*) = sqlite3GlobalConfig.mutex; |
︙ | ︙ |
Changes to src/mutex.c.
︙ | ︙ | |||
18 19 20 21 22 23 24 | #if defined(SQLITE_DEBUG) && !defined(SQLITE_MUTEX_OMIT) /* ** For debugging purposes, record when the mutex subsystem is initialized ** and uninitialized so that we can assert() if there is an attempt to ** allocate a mutex while the system is uninitialized. */ static SQLITE_WSD int mutexIsInit = 0; | | > > > > > > > > > > > > > > > > > > > | > | < | < < < < < < < < | 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 | #if defined(SQLITE_DEBUG) && !defined(SQLITE_MUTEX_OMIT) /* ** For debugging purposes, record when the mutex subsystem is initialized ** and uninitialized so that we can assert() if there is an attempt to ** allocate a mutex while the system is uninitialized. */ static SQLITE_WSD int mutexIsInit = 0; #endif /* SQLITE_DEBUG && !defined(SQLITE_MUTEX_OMIT) */ #ifndef SQLITE_MUTEX_OMIT /* ** Copies a mutex implementation. Both arguments must point to valid ** memory. */ static void mutexCopy( sqlite3_mutex_methods *pTo, sqlite3_mutex_methods const *pFrom ){ pTo->xMutexInit = pFrom->xMutexInit; pTo->xMutexEnd = pFrom->xMutexEnd; pTo->xMutexFree = pFrom->xMutexFree; pTo->xMutexEnter = pFrom->xMutexEnter; pTo->xMutexTry = pFrom->xMutexTry; pTo->xMutexLeave = pFrom->xMutexLeave; pTo->xMutexHeld = pFrom->xMutexHeld; pTo->xMutexNotheld = pFrom->xMutexNotheld; pTo->xMutexAlloc = pFrom->xMutexAlloc; } /* ** Initialize the mutex system. */ int sqlite3MutexInit(void){ int rc; if( sqlite3CompareAndSwap((void * volatile *)&sqlite3GlobalConfig.pMutex, 0, &sqlite3GlobalConfig.mutex)==0 ){ /* If the xMutexAlloc method has not been set, then the user did not ** install a mutex implementation via sqlite3_config() prior to ** sqlite3_initialize() being called. This block copies pointers to ** the default implementation into the sqlite3GlobalConfig structure. */ sqlite3_mutex_methods const *pFrom; if( sqlite3GlobalConfig.bCoreMutex ){ pFrom = sqlite3DefaultMutex(); }else{ pFrom = sqlite3NoopMutex(); } mutexCopy(&sqlite3GlobalConfig.mutex, pFrom); sqlite3MemoryBarrier(); } rc = sqlite3GlobalConfig.mutex.xMutexInit(); #ifdef SQLITE_DEBUG GLOBAL(int, mutexIsInit) = 1; #endif |
︙ | ︙ |
Changes to src/mutex_noop.c.
︙ | ︙ | |||
24 25 26 27 28 29 30 31 32 33 34 35 36 37 | ** If compiled with SQLITE_DEBUG, then additional logic is inserted ** that does error checking on mutexes to make sure they are being ** called correctly. */ #include "sqliteInt.h" #ifndef SQLITE_MUTEX_OMIT #ifndef SQLITE_DEBUG /* ** Stub routines for all mutex methods. ** ** This routines provide no mutual exclusion or error checking. */ | > > > > > > > > > > > > > > > > > > > > > > | 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | ** If compiled with SQLITE_DEBUG, then additional logic is inserted ** that does error checking on mutexes to make sure they are being ** called correctly. */ #include "sqliteInt.h" #ifndef SQLITE_MUTEX_OMIT /* ** Try to provide an atomic compare-and-swap operation on a void pointer, ** needed for initialization only. */ void *sqlite3NoopCompareAndSwap( void *volatile *pCurVal, void *cmpVal, void *swapVal ){ /* ** This platform may not have a way to perform an atomic compare-and-swap ** operation; therefore, use the fallback algorithm. ** ** WARNING: This code is almost certainly not thread-safe. */ void *oldVal = *pCurVal; if( oldVal==cmpVal ){ *pCurVal = swapVal; } return oldVal; } #ifndef SQLITE_DEBUG /* ** Stub routines for all mutex methods. ** ** This routines provide no mutual exclusion or error checking. */ |
︙ | ︙ |
Changes to src/mutex_unix.c.
︙ | ︙ | |||
82 83 84 85 86 87 88 | /* ** Try to provide a memory barrier operation, needed for initialization only. */ void sqlite3MemoryBarrier(void){ #if defined(SQLITE_MEMORY_BARRIER) SQLITE_MEMORY_BARRIER; | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | /* ** Try to provide a memory barrier operation, needed for initialization only. */ void sqlite3MemoryBarrier(void){ #if defined(SQLITE_MEMORY_BARRIER) SQLITE_MEMORY_BARRIER; #elif defined(__GNUC__) && GCC_VERSION>=4001000 __sync_synchronize(); #endif } /* ** Try to provide an atomic compare-and-swap operation on a void pointer, ** needed for initialization only. */ void *sqlite3CompareAndSwap( void *volatile *pCurVal, void *cmpVal, void *swapVal ){ #if defined(SQLITE_COMPARE_AND_SWAP) return SQLITE_COMPARE_AND_SWAP(pCurVal, cmpVal, swapVal); #elif defined(__GNUC__) && GCC_VERSION>=4001000 && SQLITE_PTRSIZE>4 return (void *)__sync_val_compare_and_swap_8( (u64 volatile *)pCurVal, (u64)cmpVal, (u64)swapVal); #elif defined(__GNUC__) && GCC_VERSION>=4001000 return (void *)__sync_val_compare_and_swap_4( (u32 volatile *)pCurVal, (u32)cmpVal, (u32)swapVal); #else /* ** This platform may not have a way to perform an atomic compare-and-swap ** operation; therefore, use the fallback algorithm. ** ** WARNING: This code is almost certainly not thread-safe. */ return sqlite3NoopCompareAndSwap(pCurVal, cmpVal, swapVal); #endif } /* ** Initialize and deinitialize the mutex subsystem. */ static int pthreadMutexInit(void){ return SQLITE_OK; } static int pthreadMutexEnd(void){ return SQLITE_OK; } |
︙ | ︙ |
Changes to src/mutex_w32.c.
︙ | ︙ | |||
85 86 87 88 89 90 91 92 93 94 95 96 97 98 | SQLITE_MEMORY_BARRIER; #elif defined(__GNUC__) __sync_synchronize(); #else MemoryBarrier(); #endif } /* ** Initialize and deinitialize the mutex subsystem. */ static sqlite3_mutex winMutex_staticMutexes[] = { SQLITE3_MUTEX_INITIALIZER, SQLITE3_MUTEX_INITIALIZER, | > > > > > > > > > > > > > > > > > > > > > > | 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 | SQLITE_MEMORY_BARRIER; #elif defined(__GNUC__) __sync_synchronize(); #else MemoryBarrier(); #endif } /* ** Try to provide an atomic compare-and-swap operation on a void pointer, ** needed for initialization only. */ void *sqlite3CompareAndSwap( void * volatile *pCurVal, void *cmpVal, void *swapVal ){ #if defined(SQLITE_COMPARE_AND_SWAP) return SQLITE_COMPARE_AND_SWAP(pCurVal, cmpVal, swapVal); #elif SQLITE_PTRSIZE>4 return (void *)InterlockedCompareExchange64( (LONGLONG SQLITE_WIN32_VOLATILE *)pCurVal, (LONGLONG)cmpVal, (LONGLONG)swapVal); #else return (void *)InterlockedCompareExchange( (LONG SQLITE_WIN32_VOLATILE *)pCurVal, (LONG)cmpVal, (LONG)swapVal); #endif } /* ** Initialize and deinitialize the mutex subsystem. */ static sqlite3_mutex winMutex_staticMutexes[] = { SQLITE3_MUTEX_INITIALIZER, SQLITE3_MUTEX_INITIALIZER, |
︙ | ︙ |
Changes to src/sqliteInt.h.
︙ | ︙ | |||
2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 | int bOpenUri; /* True to interpret filenames as URIs */ int bUseCis; /* Use covering indices for full-scans */ int mxStrlen; /* Maximum string length */ int neverCorrupt; /* Database is always well-formed */ int szLookaside; /* Default lookaside buffer size */ int nLookaside; /* Default lookaside buffer count */ sqlite3_mem_methods m; /* Low-level memory allocation interface */ sqlite3_mutex_methods mutex; /* Low-level mutex interface */ sqlite3_pcache_methods2 pcache2; /* Low-level page-cache interface */ void *pHeap; /* Heap storage space */ int nHeap; /* Size of pHeap[] */ int mnReq, mxReq; /* Min and max heap requests sizes */ sqlite3_int64 szMmap; /* mmap() space per open file */ sqlite3_int64 mxMmap; /* Maximum value for szMmap */ | > | 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 | int bOpenUri; /* True to interpret filenames as URIs */ int bUseCis; /* Use covering indices for full-scans */ int mxStrlen; /* Maximum string length */ int neverCorrupt; /* Database is always well-formed */ int szLookaside; /* Default lookaside buffer size */ int nLookaside; /* Default lookaside buffer count */ sqlite3_mem_methods m; /* Low-level memory allocation interface */ sqlite3_mutex_methods *pMutex; /* Address of mutex member or zero. */ sqlite3_mutex_methods mutex; /* Low-level mutex interface */ sqlite3_pcache_methods2 pcache2; /* Low-level page-cache interface */ void *pHeap; /* Heap storage space */ int nHeap; /* Size of pHeap[] */ int mnReq, mxReq; /* Min and max heap requests sizes */ sqlite3_int64 szMmap; /* mmap() space per open file */ sqlite3_int64 mxMmap; /* Maximum value for szMmap */ |
︙ | ︙ | |||
3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 | const sqlite3_mem_methods *sqlite3MemGetMemsys5(void); #endif #ifndef SQLITE_MUTEX_OMIT sqlite3_mutex_methods const *sqlite3DefaultMutex(void); sqlite3_mutex_methods const *sqlite3NoopMutex(void); sqlite3_mutex *sqlite3MutexAlloc(int); int sqlite3MutexInit(void); int sqlite3MutexEnd(void); #endif #if !defined(SQLITE_MUTEX_OMIT) && !defined(SQLITE_MUTEX_NOOP) void sqlite3MemoryBarrier(void); #else | > | > > > > > > > > > | 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 | const sqlite3_mem_methods *sqlite3MemGetMemsys5(void); #endif #ifndef SQLITE_MUTEX_OMIT sqlite3_mutex_methods const *sqlite3DefaultMutex(void); sqlite3_mutex_methods const *sqlite3NoopMutex(void); void *sqlite3NoopCompareAndSwap(void * volatile *, void *, void *); sqlite3_mutex *sqlite3MutexAlloc(int); int sqlite3MutexInit(void); int sqlite3MutexEnd(void); #endif #if !defined(SQLITE_MUTEX_OMIT) && !defined(SQLITE_MUTEX_NOOP) void sqlite3MemoryBarrier(void); #else # define sqlite3MemoryBarrier() #endif #if !defined(SQLITE_MUTEX_OMIT) # if !defined(SQLITE_MUTEX_NOOP) void *sqlite3CompareAndSwap(void * volatile *, void *, void *); # else # define sqlite3CompareAndSwap sqlite3NoopCompareAndSwap # endif #else # define sqlite3CompareAndSwap(x,y,z) #endif sqlite3_int64 sqlite3StatusValue(int); void sqlite3StatusUp(int, int); void sqlite3StatusDown(int, int); void sqlite3StatusSet(int, int); |
︙ | ︙ |