Do not call the xDisconnect method on a virtual table while xUpdate is
pending. Instead, defer the xDisconnect until after xUpdate completes. (CVS 3387)
FossilOrigin-Name: 61148f4c36255c4ed3552f888fa75252b300589d
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index bf571ca..5826854 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -11,7 +11,7 @@
*************************************************************************
** Internal interface definitions for SQLite.
**
-** @(#) $Id: sqliteInt.h,v 1.524 2006/08/23 20:07:22 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.525 2006/09/02 20:57:52 drh Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_
@@ -1862,6 +1862,8 @@
int sqlite3VtabRollback(sqlite3 *db);
int sqlite3VtabCommit(sqlite3 *db);
#endif
+void sqlite3VtabLock(sqlite3_vtab*);
+void sqlite3VtabUnlock(sqlite3_vtab*);
void sqlite3VtabBeginParse(Parse*, Token*, Token*, Token*);
void sqlite3VtabFinishParse(Parse*, Token*);
void sqlite3VtabArgInit(Parse*);
diff --git a/src/vdbe.c b/src/vdbe.c
index 3df482b..e4540da 100644
--- a/src/vdbe.c
+++ b/src/vdbe.c
@@ -43,7 +43,7 @@
** in this file for details. If in doubt, do not deviate from existing
** commenting and indentation practices when changing or adding code.
**
-** $Id: vdbe.c,v 1.574 2006/08/15 14:21:16 drh Exp $
+** $Id: vdbe.c,v 1.575 2006/09/02 20:57:52 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
@@ -4857,7 +4857,9 @@
apArg[i] = pX;
}
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
+ sqlite3VtabLock(pVtab);
rc = pModule->xUpdate(pVtab, nArg, apArg, &rowid);
+ sqlite3VtabUnlock(pVtab);
if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
if( pOp->p1 && rc==SQLITE_OK ){
assert( nArg>1 && apArg[0] && (apArg[0]->flags&MEM_Null) );
diff --git a/src/vtab.c b/src/vtab.c
index be6b988..9207fc4 100644
--- a/src/vtab.c
+++ b/src/vtab.c
@@ -11,7 +11,7 @@
*************************************************************************
** This file contains code used to help implement virtual tables.
**
-** $Id: vtab.c,v 1.30 2006/09/02 14:17:00 drh Exp $
+** $Id: vtab.c,v 1.31 2006/09/02 20:57:52 drh Exp $
*/
#ifndef SQLITE_OMIT_VIRTUALTABLE
#include "sqliteInt.h"
@@ -41,6 +41,29 @@
}
/*
+** Lock the virtual table so that it cannot be disconnected.
+** Locks nest. Every lock should have a corresponding unlock.
+** If an unlock is omitted, resources leaks will occur.
+**
+** If a disconnect is attempted while a virtual table is locked,
+** the disconnect is deferred until all locks have been removed.
+*/
+void sqlite3VtabLock(sqlite3_vtab *pVtab){
+ pVtab->nRef++;
+}
+
+/*
+** Unlock a virtual table. When the last lock is removed,
+** disconnect the virtual table.
+*/
+void sqlite3VtabUnlock(sqlite3_vtab *pVtab){
+ pVtab->nRef--;
+ if( pVtab->nRef==0 ){
+ pVtab->pModule->xDisconnect(pVtab);
+ }
+}
+
+/*
** Clear any and all virtual-table information from the Table record.
** This routine is called, for example, just before deleting the Table
** record.
@@ -49,10 +72,7 @@
sqlite3_vtab *pVtab = p->pVtab;
if( pVtab ){
assert( p->pMod && p->pMod->pModule );
- pVtab->nRef--;
- if( pVtab->nRef==0 ){
- pVtab->pModule->xDisconnect(pVtab);
- }
+ sqlite3VtabUnlock(pVtab);
p->pVtab = 0;
}
if( p->azModuleArg ){
@@ -359,7 +379,7 @@
/* Add pVtab to the end of sqlite3.aVTrans */
db->aVTrans[db->nVTrans++] = pVtab;
- pVtab->nRef++;
+ sqlite3VtabLock(pVtab);
return SQLITE_OK;
}
@@ -492,10 +512,7 @@
int (*x)(sqlite3_vtab *);
x = *(int (**)(sqlite3_vtab *))((char *)pVtab->pModule + offset);
if( x ) x(pVtab);
- pVtab->nRef--;
- if( pVtab->nRef==0 ){
- pVtab->pModule->xDisconnect(pVtab);
- }
+ sqlite3VtabUnlock(pVtab);
}
sqliteFree(db->aVTrans);
db->nVTrans = 0;