From e720f1ffcbf36bfd539f3a1a534c9f0e2614c199 Mon Sep 17 00:00:00 2001 From: Repinoid Date: Sun, 11 Oct 2026 08:34:01 +0300 Subject: [PATCH] =?UTF-8?q?gosqs:=20=D0=B7=D0=B0=D0=BF=D1=80=D0=B5=D1=82?= =?UTF-8?q?=D0=B8=D1=82=D1=8C=20self/cyclic=20RedrivePolicy=20(=D0=B8?= =?UTF-8?q?=D0=BD=D0=B0=D1=87=D0=B5=20deadlock=20=D0=BF=D1=80=D0=B8=20?= =?UTF-8?q?=D0=BF=D0=B5=D1=80=D0=B5=D0=BD=D0=BE=D1=81=D0=B5=20=D0=B2=20DLQ?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/gosqs/queue_attributes.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/app/gosqs/queue_attributes.go b/app/gosqs/queue_attributes.go index 341db23..149ed82 100644 --- a/app/gosqs/queue_attributes.go +++ b/app/gosqs/queue_attributes.go @@ -84,6 +84,21 @@ func setQueueAttributesV1(q *models.Queue, attr models.QueueAttributes, provided log.Error("Invalid RedrivePolicy Attribute") return fmt.Errorf("InvalidAttributeValue") } + // Запрет self-DLQ (q → q) и циклов (A → B → A): при переносе в DLQ + // переносящий код берёт DeadLetterQueue.LockMu() под уже взятым q.mu — + // self/цикл даёт немедленный self-deadlock (или AB/BA-deadlock). + if deadLetterQueue == q { + log.Error("Invalid RedrivePolicy Attribute: self DLQ") + return fmt.Errorf("InvalidAttributeValue") + } + // Обход цепочки DLQ для детекта циклов. Лимит 100 — защита от уже + // существующего в данных цикла (если бы он там был). + for cur, steps := deadLetterQueue, 0; cur != nil && steps < 100; cur, steps = cur.DeadLetterQueue, steps+1 { + if cur == q { + log.Error("Invalid RedrivePolicy Attribute: cyclic DLQ") + return fmt.Errorf("InvalidAttributeValue") + } + } q.DeadLetterQueue = deadLetterQueue q.MaxReceiveCount = attr.RedrivePolicy.MaxReceiveCount.Int() }