From: stephan Date: Thu, 24 Aug 2023 22:28:44 +0000 (+0000) Subject: Re-frame the incongruous SQLite3Jni.uncacheThread() API as sqlite3_java_uncache_thread(). X-Git-Tag: version-3.44.0~297 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=3401736694774fd49db14244d15fdbce2eb5b9e4;p=thirdparty%2Fsqlite.git Re-frame the incongruous SQLite3Jni.uncacheThread() API as sqlite3_java_uncache_thread(). FossilOrigin-Name: 7232b033954fae40df3db43e489e0e5a703c03308f500a1ae36fd9d707632d7f --- diff --git a/ext/jni/src/c/sqlite3-jni.c b/ext/jni/src/c/sqlite3-jni.c index d475c15123..410d42c818 100644 --- a/ext/jni/src/c/sqlite3-jni.c +++ b/ext/jni/src/c/sqlite3-jni.c @@ -547,48 +547,49 @@ static void s3jni_incr( volatile unsigned int * const p ){ #endif /* Helpers for working with specific mutexes. */ -#define S3JniMutex_Env_assertLocked \ +#define S3JniMutex_Env_assertLocked \ assert( 0 != SJG.envCache.locker && "Misuse of S3JniGlobal.envCache.mutex" ) -#define S3JniMutex_Env_assertLocker \ +#define S3JniMutex_Env_assertLocker \ assert( (env) == SJG.envCache.locker && "Misuse of S3JniGlobal.envCache.mutex" ) -#define S3JniMutex_Env_assertNotLocker \ +#define S3JniMutex_Env_assertNotLocker \ assert( (env) != SJG.envCache.locker && "Misuse of S3JniGlobal.envCache.mutex" ) -#define S3JniMutex_Env_enter \ - S3JniMutex_Env_assertNotLocker; \ +#define S3JniMutex_Env_enter \ + S3JniMutex_Env_assertNotLocker; \ /*MARKER(("Entering ENV mutex@%p %s.\n", env));*/ \ sqlite3_mutex_enter( SJG.envCache.mutex ); \ ++SJG.metrics.nMutexEnv; \ SJG.envCache.locker = env -#define S3JniMutex_Env_leave \ +#define S3JniMutex_Env_leave \ /*MARKER(("Leaving ENV mutex @%p %s.\n", env));*/ \ - S3JniMutex_Env_assertLocker; \ + S3JniMutex_Env_assertLocker; \ SJG.envCache.locker = 0; \ sqlite3_mutex_leave( SJG.envCache.mutex ) -#define S3JniMutex_Ext_enter \ +#define S3JniMutex_Ext_enter \ /*MARKER(("Entering autoExt mutex@%p %s.\n", env));*/ \ sqlite3_mutex_enter( SJG.autoExt.mutex ); \ ++SJG.metrics.nMutexAutoExt -#define S3JniMutex_Ext_leave \ +#define S3JniMutex_Ext_leave \ /*MARKER(("Leaving autoExt mutex@%p %s.\n", env));*/ \ sqlite3_mutex_leave( SJG.autoExt.mutex ) -#define S3JniMutex_Nph_enter \ - S3JniMutex_Env_assertNotLocker; \ +#define S3JniMutex_Nph_enter \ + S3JniMutex_Env_assertNotLocker; \ /*MARKER(("Entering NPH mutex@%p %s.\n", env));*/ \ sqlite3_mutex_enter( SJG.envCache.mutex ); \ ++SJG.metrics.nMutexEnv2; \ SJG.envCache.locker = env -#define S3JniMutex_Nph_leave \ +#define S3JniMutex_Nph_leave \ /*MARKER(("Leaving NPH mutex @%p %s.\n", env));*/ \ S3JniMutex_Env_assertLocker; \ SJG.envCache.locker = 0; \ sqlite3_mutex_leave( SJG.envCache.mutex ) -#define S3JniMutex_Pdb_enter \ - /*MARKER(("Entering PerDb mutex@%p %s.\n", env));*/ \ +#define S3JniMutex_S3JniDb_enter \ sqlite3_mutex_enter( SJG.perDb.mutex ); \ + assert( 0==SJG.perDb.locker ); \ ++SJG.metrics.nMutexPerDb; \ SJG.perDb.locker = env; -#define S3JniMutex_Pdb_leave \ +#define S3JniMutex_S3JniDb_leave \ /*MARKER(("Leaving PerDb mutex@%p %s.\n", env));*/ \ + assert( env == SJG.perDb.locker ); \ SJG.perDb.locker = 0; \ sqlite3_mutex_leave( SJG.perDb.mutex ) @@ -890,7 +891,7 @@ static void s3jni_call_xDestroy(JNIEnv * const env, jobject jObj){ ** references. */ static void S3JniHook_unref(JNIEnv * const env, S3JniHook * const s, int doXDestroy){ - if(doXDestroy && s->jObj){ + if( doXDestroy && s->jObj ){ s3jni_call_xDestroy(env, s->jObj); } UNREF_G(s->jObj); @@ -900,9 +901,9 @@ static void S3JniHook_unref(JNIEnv * const env, S3JniHook * const s, int doXDest /* ** Clears s's state and moves it to the free-list. */ -static void S3JniDb_set_aside(JNIEnv * env, S3JniDb * const s){ - if(s){ - S3JniMutex_Pdb_enter; +static void S3JniDb_set_aside_unlocked(JNIEnv * env, S3JniDb * const s){ + if( s ){ + assert( S3JniGlobal.perDb.locker == env ); assert(s->pPrev != s); assert(s->pNext != s); assert(s->pPrev ? (s->pPrev!=s->pNext) : 1); @@ -932,7 +933,13 @@ static void S3JniDb_set_aside(JNIEnv * env, S3JniDb * const s){ s->pNext = SJG.perDb.aFree; if(s->pNext) s->pNext->pPrev = s; SJG.perDb.aFree = s; - S3JniMutex_Pdb_leave; + } +} +static void S3JniDb_set_aside(JNIEnv * env, S3JniDb * const s){ + if( s ){ + S3JniMutex_S3JniDb_enter; + S3JniDb_set_aside_unlocked(env, s); + S3JniMutex_S3JniDb_leave; } } @@ -1064,7 +1071,7 @@ static void * NativePointerHolder_get(JNIEnv * env, jobject pObj, S3NphRef const static S3JniDb * S3JniDb_alloc(JNIEnv * const env, sqlite3 *pDb, jobject jDb){ S3JniDb * rv; - S3JniMutex_Pdb_enter; + S3JniMutex_S3JniDb_enter; if( SJG.perDb.aFree ){ rv = SJG.perDb.aFree; SJG.perDb.aFree = rv->pNext; @@ -1095,7 +1102,7 @@ static S3JniDb * S3JniDb_alloc(JNIEnv * const env, sqlite3 *pDb, rv->jDb = REF_G(jDb); rv->pDb = pDb; } - S3JniMutex_Pdb_leave; + S3JniMutex_S3JniDb_leave; return rv; } @@ -1113,7 +1120,7 @@ static S3JniDb * S3JniDb_alloc(JNIEnv * const env, sqlite3 *pDb, static S3JniDb * S3JniDb_for_db(JNIEnv * const env, jobject jDb, sqlite3 *pDb){ S3JniDb * s = 0; if( jDb || pDb ){ - S3JniMutex_Pdb_enter; + S3JniMutex_S3JniDb_enter; s = SJG.perDb.aUsed; if( !pDb ){ assert( jDb ); @@ -1124,7 +1131,7 @@ static S3JniDb * S3JniDb_for_db(JNIEnv * const env, jobject jDb, sqlite3 *pDb){ break; } } - S3JniMutex_Pdb_leave; + S3JniMutex_S3JniDb_leave; } return s; } @@ -2713,6 +2720,21 @@ S3JniApi(sqlite3_is_interrupted(),jboolean,1is_1interrupted)( return rc ? JNI_TRUE : JNI_FALSE; } +/* +** Uncaches the current JNIEnv from the S3JniGlobal state, clearing any +** resources owned by that cache entry and making that slot available +** for re-use. It is important that the Java-side decl of this +** function be declared as synchronous. +*/ +JniDecl(jboolean,1java_1uncache_1thread)(JniArgsEnvClass){ + int rc; + S3JniMutex_Env_enter; + rc = S3JniGlobal_env_uncache(env); + S3JniMutex_Env_leave; + return rc ? JNI_TRUE : JNI_FALSE; +} + + S3JniApi(sqlite3_last_insert_rowid(),jlong,1last_1insert_1rowid)( JniArgsEnvClass, jobject jpDb ){ @@ -3546,8 +3568,19 @@ S3JniApi(sqlite3_shutdown(),jint,1shutdown)( S3JniGlobal_env_uncache( SJG.envCache.aHead->env ); } S3JniMutex_Env_leave; - /* Do not clear S3JniGlobal.jvm: it's legal to call - sqlite3_initialize() again to restart the lib. */ +#if 0 + /* + ** Is this a good idea? We will get rid of the perDb list once + ** sqlite3 gets a per-db client state, at which point we won't have + ** a central list of databases to close. + */ + S3JniMutex_S3JniDb_enter; + while( SJG.perDb.pHead ){ + s3jni_close_db(env, SJG.perDb.pHead->jDb, 2); + } + S3JniMutex_S3JniDb_leave; +#endif + /* Do not clear S3JniGlobal.jvm: it's legal to restart the lib. */ return sqlite3_shutdown(); } @@ -4615,22 +4648,6 @@ Java_org_sqlite_jni_tester_SQLTester_installCustomExtensions(JniArgsEnvClass){ // End of SQLTester bindings. Start of lower-level bits. //////////////////////////////////////////////////////////////////////// - -/* -** Uncaches the current JNIEnv from the S3JniGlobal state, clearing any -** resources owned by that cache entry and making that slot available -** for re-use. It is important that the Java-side decl of this -** function be declared as synchronous. -*/ -JNIEXPORT jboolean JNICALL -Java_org_sqlite_jni_SQLite3Jni_uncacheJniEnv(JniArgsEnvClass){ - int rc; - S3JniMutex_Env_enter; - rc = S3JniGlobal_env_uncache(env); - S3JniMutex_Env_leave; - return rc ? JNI_TRUE : JNI_FALSE; -} - /* ** Called during static init of the SQLite3Jni class to sync certain ** compile-time constants to Java-space. diff --git a/ext/jni/src/c/sqlite3-jni.h b/ext/jni/src/c/sqlite3-jni.h index e642241921..d952cfa60a 100644 --- a/ext/jni/src/c/sqlite3-jni.h +++ b/ext/jni/src/c/sqlite3-jni.h @@ -765,10 +765,10 @@ JNIEXPORT void JNICALL Java_org_sqlite_jni_SQLite3Jni_init /* * Class: org_sqlite_jni_SQLite3Jni - * Method: uncacheJniEnv + * Method: sqlite3_java_uncache_thread * Signature: ()Z */ -JNIEXPORT jboolean JNICALL Java_org_sqlite_jni_SQLite3Jni_uncacheJniEnv +JNIEXPORT jboolean JNICALL Java_org_sqlite_jni_SQLite3Jni_sqlite3_1java_1uncache_1thread (JNIEnv *, jclass); /* diff --git a/ext/jni/src/org/sqlite/jni/SQLite3Jni.java b/ext/jni/src/org/sqlite/jni/SQLite3Jni.java index 21a93501e1..b5cde41c1b 100644 --- a/ext/jni/src/org/sqlite/jni/SQLite3Jni.java +++ b/ext/jni/src/org/sqlite/jni/SQLite3Jni.java @@ -121,10 +121,9 @@ public final class SQLite3Jni { /** Each thread which uses the SQLite3 JNI APIs should call - uncacheJniEnv() when it is done with the library - either right - before it terminates or when it is finished using the SQLite API. - This will clean up any cached per-JNIEnv info. Calling into the - library will re-initialize the cache on demand. + sqlite3_jni_uncache_thread() when it is done with the library - + either right before it terminates or when it finishes using the + SQLite API. This will clean up any cached per-thread info.

This process does not close any databases or finalize any prepared statements because their ownership does not depend on @@ -133,10 +132,9 @@ public final class SQLite3Jni { all databases before calling this function.

Calling this from the main application thread is not strictly - required but is "polite." Additional threads must call this - before ending or they will leak cache entries in the C heap, - which in turn may keep numerous Java-side global references - active. + required. Additional threads must call this before ending or they + will leak cache entries in the C heap, which in turn may keep + numerous Java-side global references active.

This routine returns false without side effects if the current JNIEnv is not cached, else returns true, but this information is @@ -144,7 +142,7 @@ public final class SQLite3Jni { which client-level code should use to make any informed decisions. */ - public static synchronized native boolean uncacheJniEnv(); + public static native boolean sqlite3_java_uncache_thread(); ////////////////////////////////////////////////////////////////////// // Maintenance reminder: please keep the sqlite3_.... functions @@ -1154,9 +1152,12 @@ public final class SQLite3Jni { ); /** - Cleans up all per-JNIEnv and per-db state managed by the library, - as well as any registered auto-extensions, then calls the - C-native sqlite3_shutdown(). + Cleans up all stale per-thread state managed by the library, as + well as any registered auto-extensions, then calls the C-native + sqlite3_shutdown(). Calling this while database handles or + prepared statements are still active will leak resources. Trying + to use those objects after this routine is called invoked + undefined behavior. */ public static synchronized native int sqlite3_shutdown(); diff --git a/ext/jni/src/org/sqlite/jni/Tester1.java b/ext/jni/src/org/sqlite/jni/Tester1.java index 89fa022cf5..cc4d7dbd06 100644 --- a/ext/jni/src/org/sqlite/jni/Tester1.java +++ b/ext/jni/src/org/sqlite/jni/Tester1.java @@ -1421,8 +1421,8 @@ public class Tester1 implements Runnable { listErrors.add(e); } }finally{ - affirm( SQLite3Jni.uncacheJniEnv() ); - affirm( !SQLite3Jni.uncacheJniEnv() ); + affirm( sqlite3_java_uncache_thread() ); + affirm( !sqlite3_java_uncache_thread() ); } } diff --git a/manifest b/manifest index 3ec95da27f..65636cb8a6 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Update\ssome\soutdated\sJNI\sdocs\sand\saccount\sfor\sa\sfunction\srenamed\searlier\sthis\sevening. -D 2023-08-24T21:45:30.722 +C Re-frame\sthe\sincongruous\sSQLite3Jni.uncacheThread()\sAPI\sas\ssqlite3_java_uncache_thread(). +D 2023-08-24T22:28:44.239 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -236,8 +236,8 @@ F ext/icu/sqliteicu.h fa373836ed5a1ee7478bdf8a1650689294e41d0c89c1daab26e9ae78a3 F ext/jni/GNUmakefile 6aeafa0ebcf0f0d834c814ae8b450b54135ea11a2a7868f90b6286ec1bf6020f F ext/jni/README.md 9d3caa2e038bfe5e8356a9e8ff66f93ca0647ac278339eeea296f10017f5cf35 F ext/jni/jar-dist.make 030aaa4ae71dd86e4ec5e7c1e6cd86f9dfa47c4592c070d2e35157e42498e1fa -F ext/jni/src/c/sqlite3-jni.c c15bd15c895ec698a669c7058cb19e8bfccdcab88dc6345357f698fbfe9544aa -F ext/jni/src/c/sqlite3-jni.h 7e9f36434b919cd8b6aa66c61e3910e9f112e252f52d1ac8a9811c52710aefcb +F ext/jni/src/c/sqlite3-jni.c e4bdcd17e8f8e825f206e1c6ab5adf7f507d70b64b0f795c0cde141077fb68b2 +F ext/jni/src/c/sqlite3-jni.h 91c2eeee22d3594e6652d51edcce0cd94d258a768802fcfac13a78f900127b72 F ext/jni/src/org/sqlite/jni/Authorizer.java 1308988f7f40579ea0e4deeaec3c6be971630566bd021c31367fe3f5140db892 F ext/jni/src/org/sqlite/jni/AutoExtension.java bcc1849b2fccbe5e2d7ac9e9ac7f8d05a6d7088a8fedbaad90e39569745a61e6 F ext/jni/src/org/sqlite/jni/BusyHandler.java 1b1d3e5c86cd796a0580c81b6af6550ad943baa25e47ada0dcca3aff3ebe978c @@ -258,8 +258,8 @@ F ext/jni/src/org/sqlite/jni/ResultCode.java ba701f20213a5f259e94cfbfdd36eb7ac7c F ext/jni/src/org/sqlite/jni/RollbackHook.java b04c8abcc6ade44a8a57129e33765793f69df0ba909e49ba18d73f4268d92564 F ext/jni/src/org/sqlite/jni/SQLFunction.java 4d6291fa14fcca1a040609378f9f00a193145d79c3abbda98ba32c340904cbeb F ext/jni/src/org/sqlite/jni/SQLLog.java c60610b35208416940822e834d61f08fbbe5d6e06b374b541b49e41fd56c9798 -F ext/jni/src/org/sqlite/jni/SQLite3Jni.java 1e791b79e96cc98a37659ea6f578ce595e1a38fb89b05e3560aa28462b283f6d -F ext/jni/src/org/sqlite/jni/Tester1.java 239eb0133547d4a23317a6dd5bc456172cfb1f2547fd15ba8408871c2776a721 +F ext/jni/src/org/sqlite/jni/SQLite3Jni.java 5fddc34787b26a494dc9843ea2530cd319dc7a6bd369fd4e86dc713f20640fa6 +F ext/jni/src/org/sqlite/jni/Tester1.java e9b82c561ec8771b3e4ea537ebd7c16dd096928b6b8221967a4726104c7c6cb2 F ext/jni/src/org/sqlite/jni/TesterFts5.java 6f135c60e24c89e8eecb9fe61dde0f3bb2906de668ca6c9186bcf34bdaf94629 F ext/jni/src/org/sqlite/jni/Tracer.java a5cece9f947b0af27669b8baec300b6dd7ff859c3e6a6e4a1bd8b50f9714775d F ext/jni/src/org/sqlite/jni/UpdateHook.java e58645a1727f8a9bbe72dc072ec5b40d9f9362cb0aa24acfe93f49ff56a9016d @@ -2096,8 +2096,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 e8308f0c6ec2d8999c8a2502fb130cb3501ba326f23f71f2cd8d452debae79b5 -R 3d26ad0e6ed454d9e8adb86ee7670851 +P 3f684ef5018116f4be46a07779451c8983ac87a5db182477f71ee7bf28287a04 +R ce1f562cc06444ed73ad1cad9371c48a U stephan -Z 11f2caacf45a97bd14e07afe2fb5856c +Z fbdf5ee5d7ecf00150898b00dcd91489 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index f2fed92de8..33b1d73d8e 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3f684ef5018116f4be46a07779451c8983ac87a5db182477f71ee7bf28287a04 \ No newline at end of file +7232b033954fae40df3db43e489e0e5a703c03308f500a1ae36fd9d707632d7f \ No newline at end of file