mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-06 15:49:35 +03:00
Fix the sqlite3_unlock_notify() interface so that when the callback is NULL
it simply cancels any outstanding callbacks. (CVS 6467) FossilOrigin-Name: 9ccfcb760745df28b04e746355b1b6dec49a93de
This commit is contained in:
16
manifest
16
manifest
@@ -1,5 +1,5 @@
|
||||
C Remove\stwo\sunused\stests\sfrom\sthe\sintegrity_check\spragma\slogic.\s(CVS\s6466)
|
||||
D 2009-04-07T22:05:43
|
||||
C Fix\sthe\ssqlite3_unlock_notify()\sinterface\sso\sthat\swhen\sthe\scallback\sis\sNULL\nit\ssimply\scancels\sany\soutstanding\scallbacks.\s(CVS\s6467)
|
||||
D 2009-04-07T22:06:57
|
||||
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
|
||||
F Makefile.in 583e87706abc3026960ed759aff6371faf84c211
|
||||
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
|
||||
@@ -136,7 +136,7 @@ F src/mutex_noop.c f5a07671f25a1a9bd7c10ad7107bc2585446200f
|
||||
F src/mutex_os2.c 6b5a74f812082a8483c3df05b47bbaac2424b9a0
|
||||
F src/mutex_unix.c 2f936339dfef1a4c142db290d575a3509b77315f
|
||||
F src/mutex_w32.c f4b6a4a48f1dfff7f0089cba9b5a371691f17b8b
|
||||
F src/notify.c da6f6b999dce9203d24280fa01b4ffbd2d9ba79b
|
||||
F src/notify.c 0127121816d8a861deb0dfd111b495346bf233db
|
||||
F src/os.c c2aa4a7d8bb845222e5c37f56cde377b20c3b087
|
||||
F src/os.h fa3f4aa0119ff721a2da4b47ffd74406ac864c05
|
||||
F src/os_common.h 8c61457df58f1a4bd5f5adc3e90e01b37bf7afbc
|
||||
@@ -159,7 +159,7 @@ F src/select.c 462d9671e91accd983110fa38674be0d2a3daa66
|
||||
F src/shell.c 0a11f831603f17fea20ca97133c0f64e716af4a7
|
||||
F src/sqlite.h.in 718a026b4cf3c766fc7ac5ff582faa60324b116c
|
||||
F src/sqlite3ext.h 1db7d63ab5de4b3e6b83dd03d1a4e64fef6d2a17
|
||||
F src/sqliteInt.h 3754c3c7f8549db259909882d3484250d77488cb
|
||||
F src/sqliteInt.h 7b341ab7d570b271e8566e7e7ed6993453f84964
|
||||
F src/sqliteLimit.h ffe93f5a0c4e7bd13e70cd7bf84cfb5c3465f45d
|
||||
F src/status.c 237b193efae0cf6ac3f0817a208de6c6c6ef6d76
|
||||
F src/table.c 332ab0ea691e63862e2a8bdfe2c0617ee61062a3
|
||||
@@ -479,7 +479,7 @@ F test/misuse.test 30b3a458e5a70c31e74c291937b6c82204c59f33
|
||||
F test/mutex1.test ebd54720401fafe854799dc86b7bf60b75631935
|
||||
F test/mutex2.test bfeaeac2e73095b2ac32285d2756e3a65e681660
|
||||
F test/nan.test c627d79b3d36ea892563fd67584b3e8a18f0618a
|
||||
F test/notify1.test 099191b6f450a7cc3208bdf826532572bdd9a204
|
||||
F test/notify1.test 533cf60a81f59c1c88a99ce46b1c14f47d14c32c
|
||||
F test/notify2.test 195a467e021f74197be2c4fb02d6dee644b8d8db
|
||||
F test/notnull.test 44d600f916b770def8b095a9962dbe3be5a70d82
|
||||
F test/null.test a8b09b8ed87852742343b33441a9240022108993
|
||||
@@ -715,7 +715,7 @@ F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81
|
||||
F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
|
||||
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
|
||||
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
|
||||
P 2c1f59834ab7a16066ee12cb8a8342d438c23ce9
|
||||
R da69fda516423dc915653709b87d09f0
|
||||
P 22999d31418aa9ecb17ab5d135b206b967889614
|
||||
R 8662e3a26c19cc89676dfbf43f445945
|
||||
U drh
|
||||
Z 1ffc7b542098adaaa0308f19da4f52e8
|
||||
Z 7764f7e6b16bc4d3ac70136f1d1dcce8
|
||||
|
||||
@@ -1 +1 @@
|
||||
22999d31418aa9ecb17ab5d135b206b967889614
|
||||
9ccfcb760745df28b04e746355b1b6dec49a93de
|
||||
40
src/notify.c
40
src/notify.c
@@ -13,7 +13,7 @@
|
||||
** This file contains the implementation of the sqlite3_unlock_notify()
|
||||
** API method and its associated functionality.
|
||||
**
|
||||
** $Id: notify.c,v 1.3 2009/04/07 11:21:29 danielk1977 Exp $
|
||||
** $Id: notify.c,v 1.4 2009/04/07 22:06:57 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "btreeInt.h"
|
||||
@@ -128,6 +128,24 @@ static void leaveMutex(void){
|
||||
|
||||
/*
|
||||
** Register an unlock-notify callback.
|
||||
**
|
||||
** This is called after connection "db" has attempted some operation
|
||||
** but has received an SQLITE_LOCKED error because another connection
|
||||
** (call it pOther) in the same process was busy using the same shared
|
||||
** cache. pOther is found by looking at db->pBlockingConnection.
|
||||
**
|
||||
** If there is no blocking connection, the callback is invoked immediately,
|
||||
** before this routine returns.
|
||||
**
|
||||
** If pOther is already blocked on db, then report SQLITE_LOCKED, to indicate
|
||||
** a deadlock.
|
||||
**
|
||||
** Otherwise, make arrangements to invoke xNotify when pOther drops
|
||||
** its locks.
|
||||
**
|
||||
** Each call to this routine overrides any prior callbacks registered
|
||||
** on the same "db". If xNotify==0 then any prior callbacks are immediately
|
||||
** cancelled.
|
||||
*/
|
||||
int sqlite3_unlock_notify(
|
||||
sqlite3 *db,
|
||||
@@ -139,7 +157,12 @@ int sqlite3_unlock_notify(
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
enterMutex();
|
||||
|
||||
if( 0==db->pBlockingConnection ){
|
||||
if( xNotify==0 ){
|
||||
removeFromBlockedList(db);
|
||||
db->pUnlockConnection = 0;
|
||||
db->xUnlockNotify = 0;
|
||||
db->pUnlockArg = 0;
|
||||
}else if( 0==db->pBlockingConnection ){
|
||||
/* The blocking transaction has been concluded. Or there never was a
|
||||
** blocking transaction. In either case, invoke the notify callback
|
||||
** immediately.
|
||||
@@ -148,7 +171,7 @@ int sqlite3_unlock_notify(
|
||||
}else{
|
||||
sqlite3 *p;
|
||||
|
||||
for(p=db->pBlockingConnection; p && p!=db; p=p->pUnlockConnection);
|
||||
for(p=db->pBlockingConnection; p && p!=db; p=p->pUnlockConnection){}
|
||||
if( p ){
|
||||
rc = SQLITE_LOCKED; /* Deadlock detected. */
|
||||
}else{
|
||||
@@ -183,7 +206,8 @@ void sqlite3ConnectionBlocked(sqlite3 *db, sqlite3 *pBlocker){
|
||||
}
|
||||
|
||||
/*
|
||||
** The transaction opened by database db has just finished. Locks held
|
||||
** This function is called when
|
||||
** the transaction opened by database db has just finished. Locks held
|
||||
** by database connection db have been released.
|
||||
**
|
||||
** This function loops through each entry in the blocked connections
|
||||
@@ -204,11 +228,11 @@ void sqlite3ConnectionUnlocked(sqlite3 *db){
|
||||
void (*xUnlockNotify)(void **, int) = 0; /* Unlock-notify cb to invoke */
|
||||
int nArg = 0; /* Number of entries in aArg[] */
|
||||
sqlite3 **pp; /* Iterator variable */
|
||||
void **aArg; /* Arguments to the unlock callback */
|
||||
void **aDyn = 0; /* Dynamically allocated space for aArg[] */
|
||||
void *aStatic[16]; /* Starter space for aArg[]. No malloc required */
|
||||
|
||||
void *aStatic[16];
|
||||
void **aArg = aStatic;
|
||||
void **aDyn = 0;
|
||||
|
||||
aArg = aStatic;
|
||||
enterMutex(); /* Enter STATIC_MASTER mutex */
|
||||
|
||||
/* This loop runs once for each entry in the blocked-connections list. */
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
*************************************************************************
|
||||
** Internal interface definitions for SQLite.
|
||||
**
|
||||
** @(#) $Id: sqliteInt.h,v 1.852 2009/04/07 14:14:22 danielk1977 Exp $
|
||||
** @(#) $Id: sqliteInt.h,v 1.853 2009/04/07 22:06:57 drh Exp $
|
||||
*/
|
||||
#ifndef _SQLITEINT_H_
|
||||
#define _SQLITEINT_H_
|
||||
@@ -836,6 +836,13 @@ struct sqlite3 {
|
||||
#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
|
||||
/* The following variables are all protected by the STATIC_MASTER
|
||||
** mutex, not by sqlite3.mutex. They are used by code in notify.c.
|
||||
**
|
||||
** When X.pUnlockConnection==Y, that means that X is waiting for Y to
|
||||
** unlock so that it can proceed.
|
||||
**
|
||||
** When X.pBlockingConnection==Y, that means that something that X tried
|
||||
** tried to do recently failed with an SQLITE_LOCKED error due to locks
|
||||
** held by Y.
|
||||
*/
|
||||
sqlite3 *pBlockingConnection; /* Connection that caused SQLITE_LOCKED */
|
||||
sqlite3 *pUnlockConnection; /* Connection to watch for unlock */
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this file is testing the sqlite3_unlock_notify() API.
|
||||
#
|
||||
# $Id: notify1.test,v 1.2 2009/03/25 15:43:09 danielk1977 Exp $
|
||||
# $Id: notify1.test,v 1.3 2009/04/07 22:06:57 drh Exp $
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
@@ -55,6 +55,38 @@ do_test notify1-1.5 {
|
||||
execsql { SELECT * FROM t1 }
|
||||
} {1 2 3 4}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Verify that invoking the "unlock_notify" method with no arguments
|
||||
# (which is the equivalent of invoking sqlite3_unlock_notify() with
|
||||
# a NULL xNotify argument) cancels a pending notify callback.
|
||||
#
|
||||
do_test notify1-1.11 {
|
||||
execsql { DROP TABLE t1; CREATE TABLE t1(a, b) }
|
||||
} {}
|
||||
do_test notify1-1.12 {
|
||||
execsql {
|
||||
BEGIN;
|
||||
INSERT INTO t1 VALUES(1, 2);
|
||||
}
|
||||
catchsql { INSERT INTO t1 VALUES(3, 4) } db2
|
||||
} {1 {database table is locked}}
|
||||
do_test notify1-1.13 {
|
||||
set zScript ""
|
||||
db2 unlock_notify {
|
||||
set zScript "db2 eval { INSERT INTO t1 VALUES(3, 4) }"
|
||||
}
|
||||
execsql { SELECT * FROM t1 }
|
||||
} {1 2}
|
||||
do_test notify1-1.14 {
|
||||
set zScript
|
||||
} {}
|
||||
do_test notify1-1.15 {
|
||||
db2 unlock_notify
|
||||
execsql { COMMIT }
|
||||
eval $zScript
|
||||
execsql { SELECT * FROM t1 }
|
||||
} {1 2}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# The following tests, notify1-2.*, test that deadlock is detected
|
||||
# correctly.
|
||||
|
||||
Reference in New Issue
Block a user