snapshot: sagernet/gvisor v0.0.0-20250811.0-sing-box-mod.1
Содержимое пина, зафиксированного в go.mod sing-box-lx, одним коммитом без истории. Полная история SagerNet/gvisor — 1.45 ГБ и клонируется в каждой CI-джобе; наша дельта — одна вставка в одну функцию, история для неё не нужна. Module path github.com/sagernet/gvisor сохранён намеренно: на него опирается replace-директива суперпроекта. Патч поверх — отдельным коммитом, чтобы дельта читалась одним git show и переносилась на новый пин копированием. SPECS/TASKS/048-GVISOR_HANDSHAKE_NIL_CRASH
This commit is contained in:
commit
2c4ae3b0a4
712 changed files with 185689 additions and 0 deletions
110
pkg/sync/checklocks_on_unsafe.go
Normal file
110
pkg/sync/checklocks_on_unsafe.go
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
// Copyright 2020 The gVisor Authors.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://developers.google.com/open-source/licenses/bsd.
|
||||
|
||||
//go:build checklocks
|
||||
// +build checklocks
|
||||
|
||||
package sync
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
"unsafe"
|
||||
|
||||
"github.com/sagernet/gvisor/pkg/goid"
|
||||
)
|
||||
|
||||
// gLocks contains metadata about the locks held by a goroutine.
|
||||
type gLocks struct {
|
||||
locksHeld []unsafe.Pointer
|
||||
}
|
||||
|
||||
// map[goid int]*gLocks
|
||||
//
|
||||
// Each key may only be written by the G with the goid it refers to.
|
||||
//
|
||||
// Note that entries are not evicted when a G exit, causing unbounded growth
|
||||
// with new G creation / destruction. If this proves problematic, entries could
|
||||
// be evicted when no locks are held at the expense of more allocations when
|
||||
// taking top-level locks.
|
||||
var locksHeld sync.Map
|
||||
|
||||
func getGLocks() *gLocks {
|
||||
id := goid.Get()
|
||||
|
||||
var locks *gLocks
|
||||
if l, ok := locksHeld.Load(id); ok {
|
||||
locks = l.(*gLocks)
|
||||
} else {
|
||||
locks = &gLocks{
|
||||
// Initialize space for a few locks.
|
||||
locksHeld: make([]unsafe.Pointer, 0, 8),
|
||||
}
|
||||
locksHeld.Store(id, locks)
|
||||
}
|
||||
|
||||
return locks
|
||||
}
|
||||
|
||||
func noteLock(l unsafe.Pointer) {
|
||||
locks := getGLocks()
|
||||
|
||||
for _, lock := range locks.locksHeld {
|
||||
if lock == l {
|
||||
panic(fmt.Sprintf("Deadlock on goroutine %d! Double lock of %p: %+v", goid.Get(), l, locks))
|
||||
}
|
||||
}
|
||||
|
||||
// Commit only after checking for panic conditions so that this lock
|
||||
// isn't on the list if the above panic is recovered.
|
||||
locks.locksHeld = append(locks.locksHeld, l)
|
||||
}
|
||||
|
||||
func noteUnlock(l unsafe.Pointer) {
|
||||
locks := getGLocks()
|
||||
|
||||
if len(locks.locksHeld) == 0 {
|
||||
panic(fmt.Sprintf("Unlock of %p on goroutine %d without any locks held! All locks:\n%s", l, goid.Get(), dumpLocks()))
|
||||
}
|
||||
|
||||
// Search backwards since callers are most likely to unlock in LIFO order.
|
||||
length := len(locks.locksHeld)
|
||||
for i := length - 1; i >= 0; i-- {
|
||||
if l == locks.locksHeld[i] {
|
||||
copy(locks.locksHeld[i:length-1], locks.locksHeld[i+1:length])
|
||||
// Clear last entry to ensure addr can be GC'd.
|
||||
locks.locksHeld[length-1] = nil
|
||||
locks.locksHeld = locks.locksHeld[:length-1]
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
panic(fmt.Sprintf("Unlock of %p on goroutine %d without matching lock! All locks:\n%s", l, goid.Get(), dumpLocks()))
|
||||
}
|
||||
|
||||
func dumpLocks() string {
|
||||
var s strings.Builder
|
||||
locksHeld.Range(func(key, value any) bool {
|
||||
goid := key.(int64)
|
||||
locks := value.(*gLocks)
|
||||
|
||||
// N.B. accessing gLocks of another G is fundamentally racy.
|
||||
|
||||
fmt.Fprintf(&s, "goroutine %d:\n", goid)
|
||||
if len(locks.locksHeld) == 0 {
|
||||
fmt.Fprintf(&s, "\t<none>\n")
|
||||
}
|
||||
for _, lock := range locks.locksHeld {
|
||||
fmt.Fprintf(&s, "\t%p\n", lock)
|
||||
}
|
||||
fmt.Fprintf(&s, "\n")
|
||||
|
||||
return true
|
||||
})
|
||||
|
||||
return s.String()
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue