snapshot: sagernet/gvisor v0.0.0-20260727.0-sing-box-mod.1 + SPEC 048 guard

Обновление снапшота с v0.0.0-20250811.0 на пин, которого требует
sing-box после мержа 235 коммитов (upstream d620bbbf2 "Update gvisor to
20260727.0"). Прежний снапшот был взят 2026-08-04 ровно с той версии,
на которой тогда стоял апстрим; разрыв возник 2026-08-05 вместе с его
бампом.

За год апстрим-gvisor изменил ~14 000 строк в 292 файлах. Значимое для
нас — сетевой стек: tcp/connect.go (PMTU-discovery + исправление
начального RTT/RTO: раньше задержка ACK внутри стека завышала стартовый
таймаут на несколько RTT), tcp/snd.go, tcp/rcv.go, stack/conntrack.go,
stack/packet_buffer.go. Всего 30 файлов в TCP и 37 в stack.

Баг SPEC 048 апстрим НЕ исправил — проверено по коду новой версии:
handleConnecting по-прежнему проверяет состояние endpoint'а, но не ep.h,
а performHandshake так же зануляет h и отпускает мьютекс до Close().
Поэтому guard перенесён (12 строк) вместе со своим тестом (45 строк).

Red/green проверен на новой базе: без guard'а тест падает с той же
nil-паникой, что в полевом крашдампе; с ним зелёный.
This commit is contained in:
Leadaxe 2026-08-05 14:53:31 +03:00
parent ffebe42860
commit 117243aa02
293 changed files with 16413 additions and 2842 deletions

View file

@ -41,6 +41,9 @@ type notifier struct {
// notifications.
epFD int
// pauseMu synchronizes notifications with save/restore.
pauseMu sync.Mutex
// mu protects fdMap.
mu sync.Mutex
@ -162,6 +165,7 @@ func (n *notifier) waitAndNotify() error {
}
notified := false
n.pauseMu.Lock()
n.mu.Lock()
for i := 0; i < v; i++ {
if fi, ok := n.fdMap[e[i].Fd]; ok {
@ -170,6 +174,7 @@ func (n *notifier) waitAndNotify() error {
}
}
n.mu.Unlock()
n.pauseMu.Unlock()
if notified {
// Let goroutines woken by Notify get a chance to run before we
// epoll_wait again.
@ -178,18 +183,31 @@ func (n *notifier) waitAndNotify() error {
}
}
// pause suspends notifications until resume is called.
func (n *notifier) pause() {
n.pauseMu.Lock()
}
// resume ends the effect of a previous call to pause.
func (n *notifier) resume() {
n.pauseMu.Unlock()
}
var shared struct {
notifier *notifier
once sync.Once
initErr error
}
// AddFD adds an FD to the list of observed FDs.
func AddFD(fd int32, queue *waiter.Queue) error {
func ensureSharedNotifier() {
shared.once.Do(func() {
shared.notifier, shared.initErr = newNotifier()
})
}
// AddFD adds an FD to the list of observed FDs.
func AddFD(fd int32, queue *waiter.Queue) error {
ensureSharedNotifier()
if shared.initErr != nil {
return shared.initErr
}
@ -213,3 +231,14 @@ func RemoveFD(fd int32) {
func HasFD(fd int32) bool {
return shared.notifier.hasFD(fd)
}
// Pause suspends notifications until Resume is called.
func Pause() {
ensureSharedNotifier()
shared.notifier.pause()
}
// Resume ends the effect of a previous call to Pause.
func Resume() {
shared.notifier.resume()
}