db: fixed issues with statement finalization (don't use weak hash)
In some cases, statements were disappearing from statement-table without being finalized; this makes disconnect fail. (I was only able to produce the problem when the db lib was instantiated in a sub custodian that is later shutdown.... like the way the rackunit gui runs the test suite.)
This commit is contained in:
parent
397702808a
commit
418985d4c4
|
@ -90,7 +90,6 @@
|
||||||
|
|
||||||
;; extension hooks: usually shouldn't need to override
|
;; extension hooks: usually shouldn't need to override
|
||||||
finalize ;; -> void
|
finalize ;; -> void
|
||||||
register-finalizer ;; -> void
|
|
||||||
|
|
||||||
;; inspection only
|
;; inspection only
|
||||||
get-param-types ;; -> (listof TypeDesc)
|
get-param-types ;; -> (listof TypeDesc)
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
racket/list
|
racket/list
|
||||||
racket/math
|
racket/math
|
||||||
ffi/unsafe
|
ffi/unsafe
|
||||||
|
ffi/unsafe/atomic
|
||||||
"../generic/interfaces.rkt"
|
"../generic/interfaces.rkt"
|
||||||
"../generic/prepared.rkt"
|
"../generic/prepared.rkt"
|
||||||
"../generic/sql-data.rkt"
|
"../generic/sql-data.rkt"
|
||||||
|
@ -24,7 +25,7 @@
|
||||||
char-mode)
|
char-mode)
|
||||||
(init strict-parameter-types?)
|
(init strict-parameter-types?)
|
||||||
|
|
||||||
(define statement-table (make-weak-hasheq))
|
(define statement-table (make-hasheq))
|
||||||
(define lock (make-semaphore 1))
|
(define lock (make-semaphore 1))
|
||||||
|
|
||||||
(define use-describe-param?
|
(define use-describe-param?
|
||||||
|
@ -437,13 +438,14 @@
|
||||||
|
|
||||||
(define/public (disconnect)
|
(define/public (disconnect)
|
||||||
(define (go)
|
(define (go)
|
||||||
|
(start-atomic)
|
||||||
(let ([db* db]
|
(let ([db* db]
|
||||||
[env* env])
|
[env* env])
|
||||||
|
(set! db #f)
|
||||||
|
(set! env #f)
|
||||||
|
(end-atomic)
|
||||||
(when db*
|
(when db*
|
||||||
(let ([statements (hash-map statement-table (lambda (k v) k))])
|
(let ([statements (hash-map statement-table (lambda (k v) k))])
|
||||||
(set! db #f)
|
|
||||||
(set! env #f)
|
|
||||||
(set! statement-table #f)
|
|
||||||
(for ([pst (in-list statements)])
|
(for ([pst (in-list statements)])
|
||||||
(free-statement* 'disconnect pst))
|
(free-statement* 'disconnect pst))
|
||||||
(handle-status 'disconnect (SQLDisconnect db*) db*)
|
(handle-status 'disconnect (SQLDisconnect db*) db*)
|
||||||
|
@ -459,11 +461,14 @@
|
||||||
(call-with-lock* 'free-statement go go #f))
|
(call-with-lock* 'free-statement go go #f))
|
||||||
|
|
||||||
(define/private (free-statement* fsym pst)
|
(define/private (free-statement* fsym pst)
|
||||||
|
(start-atomic)
|
||||||
(let ([stmt (send pst get-handle)])
|
(let ([stmt (send pst get-handle)])
|
||||||
|
(send pst set-handle #f)
|
||||||
|
(end-atomic)
|
||||||
(when stmt
|
(when stmt
|
||||||
(send pst set-handle #f)
|
|
||||||
(handle-status 'free-statement (SQLFreeStmt stmt SQL_CLOSE) stmt)
|
(handle-status 'free-statement (SQLFreeStmt stmt SQL_CLOSE) stmt)
|
||||||
(handle-status 'free-statement (SQLFreeHandle SQL_HANDLE_STMT stmt) stmt)
|
(handle-status 'free-statement (SQLFreeHandle SQL_HANDLE_STMT stmt) stmt)
|
||||||
|
(hash-remove! statement-table pst)
|
||||||
(void))))
|
(void))))
|
||||||
|
|
||||||
;; Transactions
|
;; Transactions
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#lang racket/base
|
#lang racket/base
|
||||||
(require racket/class
|
(require racket/class
|
||||||
ffi/unsafe
|
ffi/unsafe
|
||||||
|
ffi/unsafe/atomic
|
||||||
"../generic/interfaces.rkt"
|
"../generic/interfaces.rkt"
|
||||||
"../generic/prepared.rkt"
|
"../generic/prepared.rkt"
|
||||||
"../generic/sql-data.rkt"
|
"../generic/sql-data.rkt"
|
||||||
|
@ -18,7 +19,7 @@
|
||||||
busy-retry-delay)
|
busy-retry-delay)
|
||||||
|
|
||||||
(define -db db)
|
(define -db db)
|
||||||
(define statement-table (make-weak-hasheq))
|
(define statement-table (make-hasheq))
|
||||||
(define saved-tx-status #f) ;; set by with-lock, only valid while locked
|
(define saved-tx-status #f) ;; set by with-lock, only valid while locked
|
||||||
|
|
||||||
(inherit call-with-lock*
|
(inherit call-with-lock*
|
||||||
|
@ -149,33 +150,35 @@
|
||||||
pst)))
|
pst)))
|
||||||
|
|
||||||
(define/public (disconnect)
|
(define/public (disconnect)
|
||||||
;; FIXME: Reorder effects to be more robust if thread killed within disconnect (?)
|
|
||||||
(define (go)
|
(define (go)
|
||||||
(when -db
|
(start-atomic)
|
||||||
(let ([db -db]
|
(let ([db -db])
|
||||||
[statements (hash-map statement-table (lambda (k v) k))])
|
(set! -db #f)
|
||||||
(set! -db #f)
|
(end-atomic)
|
||||||
(set! statement-table #f)
|
(when db
|
||||||
(for ([pst (in-list statements)])
|
(let ([statements (hash-map statement-table (lambda (k v) k))])
|
||||||
(let ([stmt (send pst get-handle)])
|
(for ([pst (in-list statements)])
|
||||||
(when stmt
|
(do-free-statement 'disconnect pst))
|
||||||
(send pst set-handle #f)
|
(HANDLE 'disconnect2 (sqlite3_close db))
|
||||||
(HANDLE 'disconnect (sqlite3_finalize stmt)))))
|
(void)))))
|
||||||
(HANDLE 'disconnect (sqlite3_close db))
|
|
||||||
(void))))
|
|
||||||
(call-with-lock* 'disconnect go go #f))
|
(call-with-lock* 'disconnect go go #f))
|
||||||
|
|
||||||
(define/public (get-base) this)
|
(define/public (get-base) this)
|
||||||
|
|
||||||
(define/public (free-statement pst)
|
(define/public (free-statement pst)
|
||||||
(define (go)
|
(define (go) (do-free-statement 'free-statement pst))
|
||||||
(let ([stmt (send pst get-handle)])
|
|
||||||
(when stmt
|
|
||||||
(send pst set-handle #f)
|
|
||||||
(HANDLE 'free-statement (sqlite3_finalize stmt))
|
|
||||||
(void))))
|
|
||||||
(call-with-lock* 'free-statement go go #f))
|
(call-with-lock* 'free-statement go go #f))
|
||||||
|
|
||||||
|
(define/private (do-free-statement fsym pst)
|
||||||
|
(start-atomic)
|
||||||
|
(let ([stmt (send pst get-handle)])
|
||||||
|
(send pst set-handle #f)
|
||||||
|
(end-atomic)
|
||||||
|
(hash-remove! statement-table pst)
|
||||||
|
(when stmt
|
||||||
|
(HANDLE fsym (sqlite3_finalize stmt))
|
||||||
|
(void))))
|
||||||
|
|
||||||
|
|
||||||
;; == Transactions
|
;; == Transactions
|
||||||
|
|
||||||
|
@ -262,7 +265,7 @@
|
||||||
;; Can't figure out how to test...
|
;; Can't figure out how to test...
|
||||||
(define/private (handle-status who s)
|
(define/private (handle-status who s)
|
||||||
(when (memv s maybe-rollback-status-list)
|
(when (memv s maybe-rollback-status-list)
|
||||||
(when (and saved-tx-status (not (get-tx-status -db))) ;; was in trans, now not
|
(when (and saved-tx-status -db (not (get-tx-status -db))) ;; was in trans, now not
|
||||||
(set! tx-status 'invalid)))
|
(set! tx-status 'invalid)))
|
||||||
(handle-status* who s -db))
|
(handle-status* who s -db))
|
||||||
|
|
||||||
|
|
|
@ -132,6 +132,14 @@
|
||||||
(_fun _sqlite3_database
|
(_fun _sqlite3_database
|
||||||
-> _bool))
|
-> _bool))
|
||||||
|
|
||||||
|
(define-sqlite sqlite3_next_stmt
|
||||||
|
(_fun _sqlite3_database _sqlite3_statement/null
|
||||||
|
-> _sqlite3_statement/null))
|
||||||
|
|
||||||
|
(define-sqlite sqlite3_sql
|
||||||
|
(_fun _sqlite3_statement
|
||||||
|
-> _string))
|
||||||
|
|
||||||
;; ----------------------------------------
|
;; ----------------------------------------
|
||||||
|
|
||||||
#|
|
#|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user