Unload shared libraries when a database connection closes. (CVS 3208)
FossilOrigin-Name: 327e6909c9d35b651ab6f3a1a270022b354538c6
diff --git a/src/loadext.c b/src/loadext.c
index 799b878..b0199b5 100644
--- a/src/loadext.c
+++ b/src/loadext.c
@@ -16,6 +16,7 @@
#define SQLITE_CORE 1 /* Disable the API redefinition in sqlite3ext.h */
#include "sqlite3ext.h"
+#include "sqliteInt.h"
#include <string.h>
#include <ctype.h>
@@ -147,8 +148,7 @@
# define SQLITE_LIBRARY_TYPE HANDLE
# define SQLITE_OPEN_LIBRARY(A) LoadLibrary(A)
# define SQLITE_FIND_SYMBOL(A,B) GetProcAddress(A,B)
-# define SQLITE_LIBRARY_ERROR(A) FreeLibrary(A)
-# define SQLITE_CLOSE_LIBRARY(A)
+# define SQLITE_CLOSE_LIBRARY(A) FreeLibrary(A)
#endif /* windows */
/*
@@ -159,8 +159,7 @@
# define SQLITE_LIBRARY_TYPE void*
# define SQLITE_OPEN_LIBRARY(A) dlopen(A, RTLD_NOW | RTLD_GLOBAL)
# define SQLITE_FIND_SYMBOL(A,B) dlsym(A,B)
-# define SQLITE_LIBRARY_ERROR(A) dlclose(A)
-# define SQLITE_CLOSE_LIBRARY(A)
+# define SQLITE_CLOSE_LIBRARY(A) dlclose(A)
#endif
/*
@@ -202,7 +201,18 @@
SQLITE_LIBRARY_TYPE handle;
int (*xInit)(sqlite3*,char**,const sqlite3_api_routines*);
char *zErrmsg = 0;
+ SQLITE_LIBRARY_TYPE *aHandle;
+ db->nExtension++;
+ aHandle = sqliteMalloc(sizeof(handle)*db->nExtension);
+ if( aHandle==0 ){
+ return SQLITE_NOMEM;
+ }
+ if( db->nExtension>0 ){
+ memcpy(aHandle, db->aExtension, sizeof(handle)*(db->nExtension-1));
+ }
+ sqliteFree(db->aExtension);
+ db->aExtension = aHandle;
if( zProc==0 ){
int i, j, n;
char *z;
@@ -244,17 +254,17 @@
*pzErrMsg = sqlite3_mprintf("no entry point [%s] in shared library [%s]",
zProc, zFile);
}
- SQLITE_LIBRARY_ERROR(handle);
+ SQLITE_CLOSE_LIBRARY(handle);
return SQLITE_ERROR;
}else if( xInit(db, &zErrmsg, &sqlite3_api) ){
if( pzErrMsg ){
*pzErrMsg = sqlite3_mprintf("error during initialization: %s", zErrmsg);
}
sqlite3_free(zErrmsg);
- SQLITE_LIBRARY_ERROR(handle);
+ SQLITE_CLOSE_LIBRARY(handle);
return SQLITE_ERROR;
}
- SQLITE_CLOSE_LIBRARY(handle);
+ ((SQLITE_LIBRARY_TYPE*)db->aExtension)[db->nExtension-1] = handle;
return SQLITE_OK;
#else
if( pzErrMsg ){
@@ -264,4 +274,17 @@
return SQLITE_ERROR;
#endif
}
+
+/*
+** Call this routine when the database connection is closing in order
+** to clean up loaded extensions
+*/
+void sqlite3CloseExtensions(sqlite3 *db){
+ int i;
+ for(i=0; i<db->nExtension; i++){
+ SQLITE_CLOSE_LIBRARY(((SQLITE_LIBRARY_TYPE*)db->aExtension)[i]);
+ }
+ sqliteFree(db->aExtension);
+}
+
#endif /* SQLITE_OMIT_LOAD_EXTENSION */
diff --git a/src/main.c b/src/main.c
index 4a13cbb..9d6cbd9 100644
--- a/src/main.c
+++ b/src/main.c
@@ -14,7 +14,7 @@
** other files are for internal use by SQLite and should not be
** accessed by users of the library.
**
-** $Id: main.c,v 1.340 2006/05/24 12:43:27 drh Exp $
+** $Id: main.c,v 1.341 2006/06/08 15:48:01 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
@@ -165,6 +165,7 @@
if( db->pErr ){
sqlite3ValueFree(db->pErr);
}
+ sqlite3CloseExtensions(db);
db->magic = SQLITE_MAGIC_ERROR;
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index 80d4a19..44210e3 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -11,7 +11,7 @@
*************************************************************************
** Internal interface definitions for SQLite.
**
-** @(#) $Id: sqliteInt.h,v 1.494 2006/05/25 12:17:31 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.495 2006/06/08 15:48:01 drh Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_
@@ -460,6 +460,8 @@
int newTnum; /* Rootpage of table being initialized */
u8 busy; /* TRUE if currently initializing */
} init;
+ int nExtension; /* Number of loaded extensions */
+ void *aExtension; /* Array of shared libraray handles */
struct Vdbe *pVdbe; /* List of active virtual machines */
int activeVdbeCnt; /* Number of vdbes currently executing */
void (*xTrace)(void*,const char*); /* Trace function */
@@ -1740,6 +1742,7 @@
void sqlite3FailedMalloc(void);
void sqlite3AbortOtherActiveVdbes(sqlite3 *, Vdbe *);
int sqlite3OpenTempDatabase(Parse *);
+void sqlite3CloseExtensions(sqlite3*);
#ifndef SQLITE_OMIT_SHARED_CACHE
void sqlite3TableLock(Parse *, int, int, u8, const char *);