From 19b534a9e25ba6a84bce819928577c3f84c7d34f Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 29 Apr 2026 22:14:23 +0000 Subject: [PATCH] fix(nestsClient): register inbound moq-lite subscription before sending Ok The publisher's inbound-bidi handler wrote SubscribeOk to the bidi before calling registerInboundSubscription. The peer's first publisher.send() after observing Ok could race the registration on dispatchers that resume the peer's continuation before the handler's (notably Windows under Dispatchers.Default), causing send to observe an empty inboundSubs and return false. Reordering makes the peer's view of Ok a happens-after of the registration. Fixes the Windows-only failure in MoqLiteSessionTest.publisher_acks_subscribe_and_pushes_group_data_on_uni_stream. --- .../nestsclient/moq/lite/MoqLiteSession.kt | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/nestsClient/src/commonMain/kotlin/com/vitorpamplona/nestsclient/moq/lite/MoqLiteSession.kt b/nestsClient/src/commonMain/kotlin/com/vitorpamplona/nestsclient/moq/lite/MoqLiteSession.kt index 573f94565..94f043bf8 100644 --- a/nestsClient/src/commonMain/kotlin/com/vitorpamplona/nestsclient/moq/lite/MoqLiteSession.kt +++ b/nestsClient/src/commonMain/kotlin/com/vitorpamplona/nestsclient/moq/lite/MoqLiteSession.kt @@ -553,6 +553,16 @@ class MoqLiteSession internal constructor( MoqLiteControlType.Subscribe -> { val subPayload = buffer.readSizePrefixed() ?: return@collect val sub = MoqLiteCodec.decodeSubscribe(subPayload) + // Register the subscription BEFORE sending Ok so the + // peer's observation of Ok is a happens-after of + // `inboundSubs += sub`. Otherwise on dispatchers that + // resume the peer's `bidi.incoming().first()` + // continuation before this coroutine's continuation + // (notably Windows under Dispatchers.Default), the + // peer's first `publisher.send` after Ok races the + // registration and observes an empty subscriber set. + publisher.registerInboundSubscription(sub) + inboundSub = sub bidi.write( MoqLiteCodec.encodeSubscribeOk( MoqLiteSubscribeOk( @@ -564,8 +574,6 @@ class MoqLiteSession internal constructor( ), ), ) - publisher.registerInboundSubscription(sub) - inboundSub = sub dispatched = true }