/** @SYMTestCaseID PDS-SQLITE3-UT-4040 @SYMTestCaseDesc SQLITE3 - mutex API tests. List of called SQLITE3 functions: - sqlite3_mutex_alloc; - sqlite3_mutex_enter; - sqlite3_mutex_free; - sqlite3_mutex_held; - sqlite3_mutex_leave; - sqlite3_mutex_notheld; - sqlite3_mutex_try; @SYMTestPriority High @SYMTestActions SQLITE3 - mutex API tests. @SYMTestExpectedResults Test must not fail @SYMREQ REQ10424 */ static void TestSqliteMutexApi() { sqlite3_mutex* mtx = 0; int err; int type; TEST(TheDb != 0); for(type=SQLITE_MUTEX_FAST;type<=SQLITE_MUTEX_STATIC_LRU2;++type) { mtx = sqlite3_mutex_alloc(type); TEST(mtx != NULL); err = sqlite3_mutex_try(mtx); TEST(err == SQLITE_BUSY || err == SQLITE_OK); sqlite3_mutex_enter(mtx); sqlite3_mutex_leave(mtx); if(type <= SQLITE_MUTEX_RECURSIVE) { sqlite3_mutex_free(mtx); } mtx = 0; } }
/* ** Usage: btree_close ID ** ** Close the given database. */ static int btree_close( void *NotUsed, Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ int argc, /* Number of arguments */ const char **argv /* Text of each argument */ ){ Btree *pBt; int rc; if( argc!=2 ){ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " ID\"", 0); return TCL_ERROR; } pBt = sqlite3TestTextToPtr(argv[1]); rc = sqlite3BtreeClose(pBt); if( rc!=SQLITE_OK ){ Tcl_AppendResult(interp, errorName(rc), 0); return TCL_ERROR; } nRefSqlite3--; if( nRefSqlite3==0 ){ sqlite3_mutex_leave(sDb.mutex); sqlite3_mutex_free(sDb.mutex); sDb.mutex = 0; sDb.pVfs = 0; } return TCL_OK; }
/* deactivate SQLCipher, most imporantly decremeting the activation count and freeing the EVP structures on the final deactivation to ensure that OpenSSL memory is cleaned up */ static int sqlcipher_openssl_deactivate(void *ctx) { CODEC_TRACE_MUTEX("sqlcipher_openssl_deactivate: entering static master mutex"); sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)); CODEC_TRACE_MUTEX("sqlcipher_openssl_deactivate: entered static master mutex"); openssl_init_count--; if(openssl_init_count == 0) { if(openssl_external_init == 0) { /* if OpenSSL hasn't be initialized externally, and the counter reaches zero after it's decremented, release EVP memory Note: this code will only be reached if OpensSSL_add_all_algorithms() is called by SQLCipher internally. This should prevent SQLCipher from "cleaning up" openssl when it was initialized externally by the program */ #if (defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER < 0x10100000L) || (defined(LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x20700000L) EVP_cleanup(); #endif } else { openssl_external_init = 0; } #ifndef SQLCIPHER_OPENSSL_NO_MUTEX_RAND CODEC_TRACE_MUTEX("sqlcipher_openssl_deactivate: freeing openssl_rand_mutex %p", openssl_rand_mutex); sqlite3_mutex_free(openssl_rand_mutex); CODEC_TRACE_MUTEX("sqlcipher_openssl_deactivate: freed openssl_rand_mutex %p", openssl_rand_mutex); openssl_rand_mutex = NULL; #endif } CODEC_TRACE_MUTEX("sqlcipher_openssl_deactivate: leaving static master mutex"); sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)); CODEC_TRACE_MUTEX("sqlcipher_openssl_deactivate: left static master mutex"); return SQLITE_OK; }
int sqlite3_embedded_shutdown() { if ( gEmbedded.isInitialized==0 ) return SQLITE_MISUSE; gEmbedded.isInitialized = 0; sqlite3_mutex_free(gEmbedded.pMutex); sqlite3_vfs_unregister(&gEmbedded.sThisVfs); memset(&gEmbedded, 0, sizeof(gEmbedded)); return SQLITE_OK; }
/* ** CAPI: Shutdown the multiplex system - sqlite3_multiplex_shutdown() ** ** All SQLite database connections must be closed before calling this ** routine. ** ** THIS ROUTINE IS NOT THREADSAFE. Call this routine exactly once while ** shutting down in order to free all remaining multiplex groups. */ int sqlite3_multiplex_shutdown(void){ if( gMultiplex.isInitialized==0 ) return SQLITE_MISUSE; if( gMultiplex.pGroups ) return SQLITE_MISUSE; gMultiplex.isInitialized = 0; sqlite3_mutex_free(gMultiplex.pMutex); sqlite3_vfs_unregister(&gMultiplex.sThisVfs); memset(&gMultiplex, 0, sizeof(gMultiplex)); return SQLITE_OK; }
/* ** CAPI: Shutdown the multiplex system - sqlite3_multiplex_shutdown() ** ** All SQLite database connections must be closed before calling this ** routine. ** ** THIS ROUTINE IS NOT THREADSAFE. Call this routine exactly once while ** shutting down in order to free all remaining multiplex groups. */ int sqlite3_multiplex_shutdown(int eForce){ int rc = SQLITE_OK; if( gMultiplex.isInitialized==0 ) return SQLITE_MISUSE; if( gMultiplex.pGroups ){ sqlite3_log(SQLITE_MISUSE, "sqlite3_multiplex_shutdown() called " "while database connections are still open"); if( !eForce ) return SQLITE_MISUSE; rc = SQLITE_MISUSE; } gMultiplex.isInitialized = 0; sqlite3_mutex_free(gMultiplex.pMutex); sqlite3_vfs_unregister(&gMultiplex.sThisVfs); memset(&gMultiplex, 0, sizeof(gMultiplex)); return rc; }
/* ** Shutdown the quota system. ** ** All SQLite database connections must be closed before calling this ** routine. ** ** THIS ROUTINE IS NOT THREADSAFE. Call this routine exactly once while ** shutting down in order to free all remaining quota groups. */ int sqlite3_quota_shutdown(void){ quotaGroup *pGroup; if( gQuota.isInitialized==0 ) return SQLITE_MISUSE; for(pGroup=gQuota.pGroup; pGroup; pGroup=pGroup->pNext){ if( quotaGroupOpenFileCount(pGroup)>0 ) return SQLITE_MISUSE; } while( gQuota.pGroup ){ pGroup = gQuota.pGroup; gQuota.pGroup = pGroup->pNext; pGroup->iLimit = 0; assert( quotaGroupOpenFileCount(pGroup)==0 ); quotaGroupDeref(pGroup); } gQuota.isInitialized = 0; sqlite3_mutex_free(gQuota.pMutex); sqlite3_vfs_unregister(&gQuota.sThisVfs); memset(&gQuota, 0, sizeof(gQuota)); return SQLITE_OK; }
void sqlcipher_deactivate() { sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)); sqlcipher_activate_count--; /* if no connections are using sqlcipher, cleanup globals */ if(sqlcipher_activate_count < 1) { sqlite3_mutex_enter(sqlcipher_provider_mutex); if(default_provider != NULL) { sqlcipher_free(default_provider, sizeof(sqlcipher_provider)); default_provider = NULL; } sqlite3_mutex_leave(sqlcipher_provider_mutex); /* last connection closed, free provider mutex*/ sqlite3_mutex_free(sqlcipher_provider_mutex); sqlcipher_provider_mutex = NULL; sqlcipher_activate_count = 0; /* reset activation count */ } sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)); }
/* deactivate SQLCipher, most imporantly decremeting the activation count and freeing the EVP structures on the final deactivation to ensure that OpenSSL memory is cleaned up */ static int sqlcipher_openssl_deactivate(void *ctx) { sqlite3_mutex_enter(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)); openssl_init_count--; if(openssl_init_count == 0) { if(openssl_external_init == 0) { /* if OpenSSL hasn't be initialized externally, and the counter reaches zero after it's decremented, release EVP memory Note: this code will only be reached if OpensSSL_add_all_algorithms() is called by SQLCipher internally. This should prevent SQLCipher from "cleaning up" openssl when it was initialized externally by the program */ EVP_cleanup(); } #ifndef SQLCIPHER_OPENSSL_NO_MUTEX_RAND sqlite3_mutex_free(openssl_rand_mutex); openssl_rand_mutex = NULL; #endif } sqlite3_mutex_leave(sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER)); return SQLITE_OK; }
static int sqlcipher_ltc_deactivate(void *ctx) { #ifndef SQLCIPHER_LTC_NO_MUTEX_RAND sqlite3_mutex_enter(ltc_rand_mutex); #endif ltc_ref_count--; if(ltc_ref_count == 0){ fortuna_done(&prng); sqlcipher_memset((void *)&prng, 0, sizeof(prng)); #ifndef SQLCIPHER_LTC_NO_MUTEX_RAND sqlite3_mutex_leave(ltc_rand_mutex); sqlite3_mutex_free(ltc_rand_mutex); ltc_rand_mutex = NULL; #endif } #ifndef SQLCIPHER_LTC_NO_MUTEX_RAND else { sqlite3_mutex_leave(ltc_rand_mutex); } #endif return SQLITE_OK; }
void spmemvfs_env_fini() { if( NULL != g_spmemvfs_env ) { spmembuffer_link_t * iter = NULL; sqlite3_vfs_unregister( (sqlite3_vfs*)&g_spmemvfs ); sqlite3_mutex_free( g_spmemvfs_env->mutex ); iter = g_spmemvfs_env->head; for( ; NULL != iter; ) { spmembuffer_link_t * next = iter->next; spmembuffer_link_free( iter ); iter = next; } free( g_spmemvfs_env ); g_spmemvfs_env = NULL; } }
/* ** Close an existing SQLite database */ EXPORT_C int sqlite3_close(sqlite3 *db){ HashElem *i; int j; if( !db ){ return SQLITE_OK; } if( sqlite3SafetyCheck(db) ){ return SQLITE_MISUSE; } sqlite3_mutex_enter(db->mutex); #ifdef SQLITE_SSE { extern void sqlite3SseCleanup(sqlite3*); sqlite3SseCleanup(db); } #endif sqlite3ResetInternalSchema(db, 0); /* If a transaction is open, the ResetInternalSchema() call above ** will not have called the xDisconnect() method on any virtual ** tables in the db->aVTrans[] array. The following sqlite3VtabRollback() ** call will do so. We need to do this before the check for active ** SQL statements below, as the v-table implementation may be storing ** some prepared statements internally. */ sqlite3VtabRollback(db); /* If there are any outstanding VMs, return SQLITE_BUSY. */ if( db->pVdbe ){ sqlite3Error(db, SQLITE_BUSY, "Unable to close due to unfinalised statements"); sqlite3_mutex_leave(db->mutex); return SQLITE_BUSY; } assert( !sqlite3SafetyCheck(db) ); /* FIX ME: db->magic may be set to SQLITE_MAGIC_CLOSED if the database ** cannot be opened for some reason. So this routine needs to run in ** that case. But maybe there should be an extra magic value for the ** "failed to open" state. ** ** TODO: Coverage tests do not test the case where this condition is ** true. It's hard to see how to cause it without messing with threads. */ if( db->magic!=SQLITE_MAGIC_CLOSED && sqlite3SafetyOn(db) ){ /* printf("DID NOT CLOSE\n"); fflush(stdout); */ sqlite3_mutex_leave(db->mutex); return SQLITE_ERROR; } for(j=0; j<db->nDb; j++){ struct Db *pDb = &db->aDb[j]; if( pDb->pBt ){ sqlite3BtreeClose(pDb->pBt); pDb->pBt = 0; if( j!=1 ){ pDb->pSchema = 0; } } } sqlite3ResetInternalSchema(db, 0); assert( db->nDb<=2 ); assert( db->aDb==db->aDbStatic ); for(i=sqliteHashFirst(&db->aFunc); i; i=sqliteHashNext(i)){ FuncDef *pFunc, *pNext; for(pFunc = (FuncDef*)sqliteHashData(i); pFunc; pFunc=pNext){ pNext = pFunc->pNext; sqlite3_free(pFunc); } } for(i=sqliteHashFirst(&db->aCollSeq); i; i=sqliteHashNext(i)){ CollSeq *pColl = (CollSeq *)sqliteHashData(i); /* Invoke any destructors registered for collation sequence user data. */ for(j=0; j<3; j++){ if( pColl[j].xDel ){ pColl[j].xDel(pColl[j].pUser); } } sqlite3_free(pColl); } sqlite3HashClear(&db->aCollSeq); #ifndef SQLITE_OMIT_VIRTUALTABLE for(i=sqliteHashFirst(&db->aModule); i; i=sqliteHashNext(i)){ Module *pMod = (Module *)sqliteHashData(i); if( pMod->xDestroy ){ pMod->xDestroy(pMod->pAux); } sqlite3_free(pMod); } sqlite3HashClear(&db->aModule); #endif sqlite3HashClear(&db->aFunc); sqlite3Error(db, SQLITE_OK, 0); /* Deallocates any cached error strings. */ if( db->pErr ){ sqlite3ValueFree(db->pErr); } sqlite3CloseExtensions(db); db->magic = SQLITE_MAGIC_ERROR; /* The temp-database schema is allocated differently from the other schema ** objects (using sqliteMalloc() directly, instead of sqlite3BtreeSchema()). ** So it needs to be freed here. Todo: Why not roll the temp schema into ** the same sqliteMalloc() as the one that allocates the database ** structure? */ sqlite3_free(db->aDb[1].pSchema); sqlite3_mutex_leave(db->mutex); sqlite3_mutex_free(db->mutex); sqlite3_free(db); return SQLITE_OK; }
void dealloc() { this->close(); sqlite3_mutex_free(mtx); sqlite3_shutdown(); }