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 *);