From cb1e4376afe9f887b9e3b3b2a9ddef116bedb0cc Mon Sep 17 00:00:00 2001 From: Paul Buetow Date: Fri, 22 May 2026 12:31:22 +0300 Subject: doc(rpn): clarify lock ordering in metric set handlers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No deadlock risk: evaluate() and RPN.SetPrefixMode() both acquire locks in the same order (r.mu → o.mu). The nested lock in evaluate() is safe — o.mu (Operations) is a separate mutex from r.mu (RPN). Resolves task ce: lock ordering analysis shows no circular wait. --- internal/rpn/rpn_parse.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/internal/rpn/rpn_parse.go b/internal/rpn/rpn_parse.go index 2d2963a..7abd41c 100644 --- a/internal/rpn/rpn_parse.go +++ b/internal/rpn/rpn_parse.go @@ -367,6 +367,9 @@ func (r *RPN) evaluate(input string, tokens []string) (string, error) { return result, nil case "binary": if i+2 < len(tokens) && tokens[i+2] == "set" { + // Lock order: r.mu → o.mu (same as RPN.SetPrefixMode) + // No deadlock risk: both paths acquire in the same direction. + // r.mu is held by evaluate(); o.mu is a separate mutex on Operations. r.prefixMode = IEC r.ops.SetPrefixMode(IEC) return "prefix mode: IEC", nil -- cgit v1.2.3