From d2fd0c0cc07029f879f6611d3b52e4c33bd78b0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristupas=20Antanavic=CC=8Cius?= Date: Mon, 12 Apr 2021 14:50:58 +0300 Subject: [PATCH] device: allocate new buffer in receive death spiral MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Note: this bug is "hidden" by avoiding "death spiral" code path by 6228659 ("device: handle broader range of errors in RoutineReceiveIncoming"). If the code reached "death spiral" mechanism, there would be multiple double frees happening. This results in a deadlock on iOS, because the pools are fixed size and goroutine might stop until somebody makes space in the pool. This was almost 100% repro on the new ARM Macbooks: - Build with 'ios' tag for Mac. This will enable bounded pools. - Somehow call device.IpcSet at least couple of times (update config) - device.BindUpdate() would be triggered - RoutineReceiveIncoming would enter "death spiral". - RoutineReceiveIncoming would stall on double free (pool is already full) - The stuck routine would deadlock 'device.closeBindLocked()' function on line 'netc.stopping.Wait()' Signed-off-by: Kristupas Antanavičius Signed-off-by: Jason A. Donenfeld --- device/receive.go | 1 + 1 file changed, 1 insertion(+) diff --git a/device/receive.go b/device/receive.go index fa5c0a6..3aa4458 100644 --- a/device/receive.go +++ b/device/receive.go @@ -104,6 +104,7 @@ func (device *Device) RoutineReceiveIncoming(recv conn.ReceiveFunc) { if deathSpiral < 10 { deathSpiral++ time.Sleep(time.Second / 3) + buffer = device.GetMessageBuffer() continue } return