fix(WRK-01): STA pump step refreshes activity to prevent false StaHung
A long legitimate ReadBulk pumped Windows messages without refreshing LastStaActivityUtc, so the watchdog false-positived StaHung past HeartbeatStuckCeiling and then silently dropped every reply. PumpPendingMessages() now calls MarkActivity() after pumping; a genuinely stuck STA (no pumping) still accrues staleness and faults correctly. No MXAccess parity change. archreview: WRK-01 (P0). Verified on the Windows host (x86): worker builds clean, StaRuntimeTests + WorkerPipeSessionTests 33/33 pass.
This commit is contained in:
@@ -85,6 +85,34 @@ public sealed class StaRuntimeTests
|
||||
Assert.True(updated);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that <see cref="StaRuntime.PumpPendingMessages"/> refreshes
|
||||
/// <see cref="StaRuntime.LastActivityUtc"/>. A long synchronous STA
|
||||
/// command (for example <c>ReadBulk</c> waiting <c>timeout_ms</c> for
|
||||
/// the first <c>OnDataChange</c>) invokes the pump step on every wait
|
||||
/// iteration while it legitimately holds the STA thread; refreshing
|
||||
/// activity here keeps the watchdog from mistaking a busy STA for a hung
|
||||
/// one (WRK-01). The runtime is deliberately left unstarted so the only
|
||||
/// source of activity is the pump call under test, not the idle loop.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void PumpPendingMessages_RefreshesLastActivity()
|
||||
{
|
||||
RecordingComApartmentInitializer initializer = new();
|
||||
using StaRuntime runtime = CreateRuntime(initializer);
|
||||
DateTimeOffset before = runtime.LastActivityUtc;
|
||||
|
||||
bool refreshed = SpinWait.SpinUntil(
|
||||
() =>
|
||||
{
|
||||
runtime.PumpPendingMessages();
|
||||
return runtime.LastActivityUtc > before;
|
||||
},
|
||||
TimeSpan.FromSeconds(2));
|
||||
|
||||
Assert.True(refreshed, "PumpPendingMessages must advance LastActivityUtc.");
|
||||
}
|
||||
|
||||
/// <summary>Verifies that InvokeAsync faults the returned task when a command raises an exception without stopping the runtime.</summary>
|
||||
/// <returns>A task that represents the asynchronous operation.</returns>
|
||||
[Fact]
|
||||
|
||||
Reference in New Issue
Block a user