From: stephan Date: Fri, 25 Aug 2023 11:32:56 +0000 (+0000) Subject: Code restructuring. Force SQLITE_THREADSAFE in JNI builds for the time being, as... X-Git-Tag: version-3.44.0~291 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=0199669fa121fd1c525066aabaff00b14a2d1b23;p=thirdparty%2Fsqlite.git Code restructuring. Force SQLITE_THREADSAFE in JNI builds for the time being, as threadsafe==0 leads to as-yet-mysterious JNI-level reference errors. FossilOrigin-Name: 5a099caa2c21bec647f0a521e7f5d0d1cc2f96d388d3d6c53d5ec80947f33e8d --- diff --git a/ext/jni/src/c/sqlite3-jni.c b/ext/jni/src/c/sqlite3-jni.c index 0d2adff5aa..4c9f5e6e5b 100644 --- a/ext/jni/src/c/sqlite3-jni.c +++ b/ext/jni/src/c/sqlite3-jni.c @@ -105,6 +105,14 @@ # define SQLITE_THREADSAFE 1 #endif +/* +** 2023-08-25: initial attempts at running with SQLITE_THREADSAFE=0 +** lead to as-yet-uninvestigated bad reference errors from JNI. +*/ +#if SQLITE_THREADSAFE==0 +# error "This code currently requires SQLITE_THREADSAFE!=0." +#endif + /**********************************************************************/ /* SQLITE_USE_... */ #ifndef SQLITE_USE_URI @@ -445,11 +453,12 @@ struct S3JniGlobalType { ** threads. Caching a copy of the JavaVM object enables any thread ** with access to the cached object to get access to its own ** JNIEnv when necessary. + ** */ JavaVM * jvm; /* - ** Cache of Java refs/IDs for NativePointerHolder subclasses. - ** Initialized on demand. + ** Cache of Java refs and method IDs for NativePointerHolder + ** subclasses. Initialized on demand. */ S3JniNphClass nph[S3Jni_NphCache_size]; /* @@ -459,24 +468,23 @@ struct S3JniGlobalType { S3JniEnv * aHead /* Linked list of in-use instances */; S3JniEnv * aFree /* Linked list of free instances */; sqlite3_mutex * mutex /* mutex for aHead and aFree as well for - first-time inits of nph members. */; + first-time inits of nph[] entries. */; void const * locker /* env mutex is held on this object's behalf. Used only for sanity checking. */; } envCache; + /* + ** Per-db state. This can move into the core library once we can tie + ** client-defined state to db handles there. + */ struct { - S3JniDb * aUsed /* Linked list of in-use instances */; + S3JniDb * aHead /* Linked list of in-use instances */; S3JniDb * aFree /* Linked list of free instances */; - sqlite3_mutex * mutex /* mutex for aUsed and aFree */; + sqlite3_mutex * mutex /* mutex for aHead and aFree */; void const * locker /* perDb mutex is held on this object's behalf. Unlike envCache.locker, we cannot always have this set to the current JNIEnv object. Used only for sanity checking. */; } perDb; -#ifdef SQLITE_ENABLE_SQLLOG - struct { - S3JniHook sqllog /* sqlite3_config(SQLITE_CONFIG_SQLLOG) callback */; - } hooks; -#endif /* ** Refs to global classes and methods. Obtained during static init ** and never released. @@ -490,6 +498,22 @@ struct S3JniGlobalType { jmethodID ctorStringBA /* the String(byte[],Charset) constructor */; jmethodID stringGetBytes /* the String.getBytes(Charset) method */; } g /* refs to global Java state */; + /** + The list of bound auto-extensions (Java-side: + org.sqlite.jni.auto_extension objects). + */ + struct { + S3JniAutoExtension *pExt /* The auto-extension list. It is + maintained such that all active + entries are in the first contiguous + nExt array elements. */; + int nAlloc /* number of entries allocated for pExt, + as distinct from the number of active + entries. */; + int nExt /* number of active entries in pExt, all in the + first nExt'th array elements. */; + sqlite3_mutex * mutex /* mutex for manipulation/traversal of pExt */; + } autoExt; #ifdef SQLITE_ENABLE_FTS5 struct { volatile jobject jFtsExt /* Global ref to Java singleton for the @@ -500,6 +524,11 @@ struct S3JniGlobalType { } jPhraseIter; } fts5; #endif +#ifdef SQLITE_ENABLE_SQLLOG + struct { + S3JniHook sqllog /* sqlite3_config(SQLITE_CONFIG_SQLLOG) callback */; + } hooks; +#endif #ifdef SQLITE_JNI_ENABLE_METRICS /* Internal metrics. */ struct { @@ -529,18 +558,6 @@ struct S3JniGlobalType { #endif } metrics; #endif /* SQLITE_JNI_ENABLE_METRICS */ - /** - The list of bound auto-extensions (Java-side: - org.sqlite.jni.auto_extension objects). - */ - struct { - S3JniAutoExtension *pExt /* Head of the auto-extension list */; - int nAlloc /* number of entries allocated for pExt, - as distinct from the number of active - entries. */; - int nExt /* number of active entries in pExt. */; - sqlite3_mutex * mutex /* mutex for manipulation/traversal of pExt */; - } autoExt; }; static S3JniGlobalType S3JniGlobal = {}; #define SJG S3JniGlobal @@ -550,23 +567,24 @@ static S3JniGlobalType S3JniGlobal = {}; #define s3jni_incr(PTR) #elif S3JNI_METRICS_MUTEX static void s3jni_incr( volatile unsigned int * const p ){ - sqlite3_mutex * const m = SJG.metrics.mutex; - sqlite3_mutex_enter(m); + sqlite3_mutex_enter(SJG.metrics.mutex); ++SJG.metrics.nMetrics; ++(*p); - sqlite3_mutex_leave(m); + sqlite3_mutex_leave(SJG.metrics.mutex); } #else #define s3jni_incr(PTR) ++(*(PTR)) #endif /* Helpers for working with specific mutexes. */ +#if SQLITE_THREADSAFE #define S3JniMutex_Env_assertLocked \ assert( 0 != SJG.envCache.locker && "Misuse of S3JniGlobal.envCache.mutex" ) #define S3JniMutex_Env_assertLocker \ assert( (env) == SJG.envCache.locker && "Misuse of S3JniGlobal.envCache.mutex" ) #define S3JniMutex_Env_assertNotLocker \ assert( (env) != SJG.envCache.locker && "Misuse of S3JniGlobal.envCache.mutex" ) + #define S3JniMutex_Env_enter \ S3JniMutex_Env_assertNotLocker; \ /*MARKER(("Entering ENV mutex@%p %s.\n", env));*/ \ @@ -606,6 +624,19 @@ static void s3jni_incr( volatile unsigned int * const p ){ assert( env == SJG.perDb.locker ); \ SJG.perDb.locker = 0; \ sqlite3_mutex_leave( SJG.perDb.mutex ) +#else /* SQLITE_THREADSAFE==0 */ +#define S3JniMutex_Env_assertLocked +#define S3JniMutex_Env_assertLocker +#define S3JniMutex_Env_assertNotLocker +#define S3JniMutex_Env_enter +#define S3JniMutex_Env_leave +#define S3JniMutex_Ext_enter +#define S3JniMutex_Ext_leave +#define S3JniMutex_Nph_enter +#define S3JniMutex_Nph_leave +#define S3JniMutex_S3JniDb_enter +#define S3JniMutex_S3JniDb_leave +#endif #define s3jni_oom_check(VAR) if( !(VAR) ) s3jni_oom(env) static inline void s3jni_oom(JNIEnv * const env){ @@ -917,15 +948,17 @@ static void S3JniHook_unref(JNIEnv * const env, S3JniHook * const s, int doXDest */ static void S3JniDb_set_aside_unlocked(JNIEnv * env, S3JniDb * const s){ if( s ){ +#if SQLITE_THREADSAFE assert( S3JniGlobal.perDb.locker == env ); +#endif assert(s->pPrev != s); assert(s->pNext != s); assert(s->pPrev ? (s->pPrev!=s->pNext) : 1); if(s->pNext) s->pNext->pPrev = s->pPrev; if(s->pPrev) s->pPrev->pNext = s->pNext; - else if(SJG.perDb.aUsed == s){ + else if(SJG.perDb.aHead == s){ assert(!s->pPrev); - SJG.perDb.aUsed = s->pNext; + SJG.perDb.aHead = s->pNext; } sqlite3_free( s->zMainDbName ); #define UNHOOK(MEMBER,XDESTROY) S3JniHook_unref(env, &s->hooks.MEMBER, XDESTROY) @@ -1107,8 +1140,8 @@ static S3JniDb * S3JniDb_alloc(JNIEnv * const env, sqlite3 *pDb, } } if( rv ){ - rv->pNext = SJG.perDb.aUsed; - SJG.perDb.aUsed = rv; + rv->pNext = SJG.perDb.aHead; + SJG.perDb.aHead = rv; if( rv->pNext ){ assert(!rv->pNext->pPrev); rv->pNext->pPrev = rv; @@ -1135,7 +1168,7 @@ static S3JniDb * S3JniDb_for_db(JNIEnv * const env, jobject jDb, sqlite3 *pDb){ S3JniDb * s = 0; if( jDb || pDb ){ S3JniMutex_S3JniDb_enter; - s = SJG.perDb.aUsed; + s = SJG.perDb.aHead; if( !pDb ){ assert( jDb ); pDb = PtrGet_sqlite3(jDb); @@ -4707,6 +4740,7 @@ Java_org_sqlite_jni_SQLite3Jni_init(JniArgsEnvClass){ {"SQLITE_MAX_TRIGGER_DEPTH", JTYPE_INT, SQLITE_MAX_TRIGGER_DEPTH}, {"SQLITE_LIMIT_WORKER_THREADS", JTYPE_INT, SQLITE_LIMIT_WORKER_THREADS}, {"SQLITE_MAX_WORKER_THREADS", JTYPE_INT, SQLITE_MAX_WORKER_THREADS}, + {"SQLITE_THREADSAFE", JTYPE_INT, SQLITE_THREADSAFE}, {0,0} }; jfieldID fieldId; @@ -4714,7 +4748,7 @@ Java_org_sqlite_jni_SQLite3Jni_init(JniArgsEnvClass){ const ConfigFlagEntry * pConfFlag; if( 0==sqlite3_threadsafe() ){ - (*env)->FatalError(env, "sqlite3 was not built with SQLITE_THREADSAFE."); + (*env)->FatalError(env, "sqlite3 currently requires SQLITE_THREADSAFE!=0."); return; } memset(&S3JniGlobal, 0, sizeof(S3JniGlobal)); diff --git a/ext/jni/src/org/sqlite/jni/SQLite3Jni.java b/ext/jni/src/org/sqlite/jni/SQLite3Jni.java index 9146e61cca..5a9e3c0805 100644 --- a/ext/jni/src/org/sqlite/jni/SQLite3Jni.java +++ b/ext/jni/src/org/sqlite/jni/SQLite3Jni.java @@ -1318,6 +1318,10 @@ public final class SQLite3Jni { public static final String SQLITE_VERSION = sqlite3_libversion(); public static final String SQLITE_SOURCE_ID = sqlite3_sourceid(); + // Initialized at static init time to the build-time value of + // SQLITE_THREADSAFE. + public static int SQLITE_THREADSAFE = -1; + // access public static final int SQLITE_ACCESS_EXISTS = 0; public static final int SQLITE_ACCESS_READWRITE = 1; diff --git a/ext/jni/src/org/sqlite/jni/Tester1.java b/ext/jni/src/org/sqlite/jni/Tester1.java index 7587cad884..1c452f720c 100644 --- a/ext/jni/src/org/sqlite/jni/Tester1.java +++ b/ext/jni/src/org/sqlite/jni/Tester1.java @@ -1530,12 +1530,29 @@ public class Tester1 implements Runnable { final long timeStart = System.currentTimeMillis(); int nLoop = 0; - affirm( 0==sqlite3_config( SQLITE_CONFIG_SINGLETHREAD ), - "Could not switch to single-thread mode." ); - affirm( 0==sqlite3_config( SQLITE_CONFIG_MULTITHREAD ), - "Could not switch to multithread mode." ); - affirm( 0==sqlite3_config( SQLITE_CONFIG_SERIALIZED ), - "Could not switch to serialized threading mode." ); + switch( SQLITE_THREADSAFE ){ /* Sanity checking */ + case 0: + affirm( 0==sqlite3_config( SQLITE_CONFIG_SINGLETHREAD ), + "Could not switch to single-thread mode." ); + affirm( 0!=sqlite3_config( SQLITE_CONFIG_MULTITHREAD ), + "Could switch to multithread mode." ); + affirm( 0!=sqlite3_config( SQLITE_CONFIG_SERIALIZED ), + "Could not switch to serialized threading mode." ); + outln("This is a single-threaded build. Not using threads."); + nThread = 1; + break; + case 1: + case 2: + affirm( 0==sqlite3_config( SQLITE_CONFIG_SINGLETHREAD ), + "Could not switch to single-thread mode." ); + affirm( 0==sqlite3_config( SQLITE_CONFIG_MULTITHREAD ), + "Could not switch to multithread mode." ); + affirm( 0==sqlite3_config( SQLITE_CONFIG_SERIALIZED ), + "Could not switch to serialized threading mode." ); + break; + default: + affirm( false, "Unhandled SQLITE_THREADSAFE value." ); + } outln("libversion_number: ", sqlite3_libversion_number(),"\n", sqlite3_libversion(),"\n",SQLITE_SOURCE_ID); diff --git a/manifest b/manifest index 347cb57fcb..88ce877e9e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Remove\sincorrect\s(but\sharmless)\sdependency\son\ssource\scode\sfile\s"sessionfuzz-data1.db"\sfrom\smain.mk\sand\sMakefile.in. -D 2023-08-25T11:06:26.590 +C Code\srestructuring.\sForce\sSQLITE_THREADSAFE\sin\sJNI\sbuilds\sfor\sthe\stime\sbeing,\sas\sthreadsafe==0\sleads\sto\sas-yet-mysterious\sJNI-level\sreference\serrors. +D 2023-08-25T11:32:56.589 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -236,7 +236,7 @@ F ext/icu/sqliteicu.h fa373836ed5a1ee7478bdf8a1650689294e41d0c89c1daab26e9ae78a3 F ext/jni/GNUmakefile 2fe04e7a7534a069ea8448f42e95bb5f8fc279ea3c9883598acedc99bbc254a7 F ext/jni/README.md 1332b1fa27918bd5d9ca2d0d4f3ac3a6ab86b9e3699dc5bfe32904a027f3d2a9 F ext/jni/jar-dist.make 030aaa4ae71dd86e4ec5e7c1e6cd86f9dfa47c4592c070d2e35157e42498e1fa -F ext/jni/src/c/sqlite3-jni.c 969e59cdf9ad2394dcfc7b7fd3e259ff27cacfbe4946ccfdb8de6554745a32cb +F ext/jni/src/c/sqlite3-jni.c 2d13c93fbf83feb2725922cc63e3157284848a435a9ff5faa8949d9157e1490f F ext/jni/src/c/sqlite3-jni.h 3d8cdacce26d20fd967d67a2e8539d38fc2e9fe13598147399db4b2c303a89c8 F ext/jni/src/org/sqlite/jni/Fts5.java a45cd890202d72c3bfe8aea69b57b02b6dd588361af81d8b921954c37940b2f7 F ext/jni/src/org/sqlite/jni/Fts5Context.java 0a5a02047a6a1dd3e4a38b0e542a8dd2de365033ba30e6ae019a676305959890 @@ -250,8 +250,8 @@ F ext/jni/src/org/sqlite/jni/Nullable.java b2f8755970e9dd0e917a505638d036ccc699c F ext/jni/src/org/sqlite/jni/OutputPointer.java 4ae06135decef35eb04498daa2868939d91a294e948747c580ef9ce31563a6b3 F ext/jni/src/org/sqlite/jni/ResultCode.java ba701f20213a5f259e94cfbfdd36eb7ac7ce7797f2c6c7fca2004ff12ce20f86 F ext/jni/src/org/sqlite/jni/SQLFunction.java 4d6291fa14fcca1a040609378f9f00a193145d79c3abbda98ba32c340904cbeb -F ext/jni/src/org/sqlite/jni/SQLite3Jni.java 92d0711f004327728704cc7ff33d9923be6c98dad50515093c96a99f34e13f9d -F ext/jni/src/org/sqlite/jni/Tester1.java 3bfbcbf0720f9b71e461eb016b8bc30289a7ceaab1aa5da13e319fd303bf19fd +F ext/jni/src/org/sqlite/jni/SQLite3Jni.java 582242f27aea55bce0d3b88dd63bea03e4cb49a8c40950ef99a7e19d9307dfb9 +F ext/jni/src/org/sqlite/jni/Tester1.java c2e3d18229e9443c3e6cf54a150cfa832219ba63a0b17f7bef102e5e4b2b2a8d F ext/jni/src/org/sqlite/jni/TesterFts5.java 6f135c60e24c89e8eecb9fe61dde0f3bb2906de668ca6c9186bcf34bdaf94629 F ext/jni/src/org/sqlite/jni/ValueHolder.java f022873abaabf64f3dd71ab0d6037c6e71cece3b8819fa10bf26a5461dc973ee F ext/jni/src/org/sqlite/jni/authorizer_callback.java 1d2d7fd584f917afa507820644d95504bcc9c5d7363a7afeb58de3b256851bfe @@ -2100,8 +2100,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 646e7fc3b5ba81c207f013c9a06781986138379f20e787320a811ba3ed5489dc -R b08c9d8a6a2483e5f535446bff4911b8 -U dan -Z 116a690cb7924a8fc2ec464347e1c482 +P 17d56c0207f63614b34ef3594d06602ab7a6e85604f3589b30aa79316f1744ee +R 0d04424045f1de02bc280794aad48b2b +U stephan +Z a29af0815bfb2df6f8dd8b5fbb60db4d # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 1b78f9a395..8c6286a678 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -17d56c0207f63614b34ef3594d06602ab7a6e85604f3589b30aa79316f1744ee \ No newline at end of file +5a099caa2c21bec647f0a521e7f5d0d1cc2f96d388d3d6c53d5ec80947f33e8d \ No newline at end of file