mirror of
https://github.com/hoernschen/dendrite.git
synced 2025-08-05 15:42:46 +00:00
HACK: Track goroutine IDs to determine when we write by the wrong thread
To use: set `DENDRITE_TRACE_SQL=1` then grep for `unsafe`
This commit is contained in:
parent
a9f4d83d30
commit
bfecc8e0e9
5 changed files with 233 additions and 6 deletions
|
@ -3,6 +3,10 @@ package sqlutil
|
|||
import (
|
||||
"database/sql"
|
||||
"errors"
|
||||
"fmt"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"go.uber.org/atomic"
|
||||
)
|
||||
|
@ -12,8 +16,9 @@ import (
|
|||
// contend on database locks in, e.g. SQLite. Only one task will run
|
||||
// at a time on a given ExclusiveWriter.
|
||||
type ExclusiveWriter struct {
|
||||
running atomic.Bool
|
||||
todo chan transactionWriterTask
|
||||
running atomic.Bool
|
||||
todo chan transactionWriterTask
|
||||
writerID int
|
||||
}
|
||||
|
||||
func NewExclusiveWriter() Writer {
|
||||
|
@ -30,6 +35,15 @@ type transactionWriterTask struct {
|
|||
wait chan error
|
||||
}
|
||||
|
||||
func (w *ExclusiveWriter) Safe() string {
|
||||
a := goid()
|
||||
b := w.writerID
|
||||
if a == b {
|
||||
return ""
|
||||
}
|
||||
return fmt.Sprintf("%v != %v", a, b)
|
||||
}
|
||||
|
||||
// Do queues a task to be run by a TransactionWriter. The function
|
||||
// provided will be ran within a transaction as supplied by the
|
||||
// txn parameter if one is supplied, and if not, will take out a
|
||||
|
@ -60,6 +74,7 @@ func (w *ExclusiveWriter) run() {
|
|||
if !w.running.CAS(false, true) {
|
||||
return
|
||||
}
|
||||
w.writerID = goid()
|
||||
defer w.running.Store(false)
|
||||
for task := range w.todo {
|
||||
if task.db != nil && task.txn != nil {
|
||||
|
@ -74,3 +89,14 @@ func (w *ExclusiveWriter) run() {
|
|||
close(task.wait)
|
||||
}
|
||||
}
|
||||
|
||||
func goid() int {
|
||||
var buf [64]byte
|
||||
n := runtime.Stack(buf[:], false)
|
||||
idField := strings.Fields(strings.TrimPrefix(string(buf[:n]), "goroutine "))[0]
|
||||
id, err := strconv.Atoi(idField)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("cannot get goroutine id: %v", err))
|
||||
}
|
||||
return id
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue