Skip to content

TwoWayAgent uses TaskContinuationOptions instead of TaskCreationOptions causing synchronous continuation deadlocks #55

@jagjit-2

Description

@jagjit-2

In TwoWayAgent.Tell(), the TaskCompletionSource is created with TaskContinuationOptions.RunContinuationsAsynchronously instead of TaskCreationOptions.RunContinuationsAsynchronously. This causes SetResult() to run continuations synchronously, leading to deadlocks when continuations attempt to send additional messages to the same Agent.

// Current (buggy) code in Agent.cs:
var tcs = new TaskCompletionSource<TReply>(TaskContinuationOptions.RunContinuationsAsynchronously);

TaskCompletionSource has no constructor accepting TaskContinuationOptions. The enum gets boxed as object and matched to the (object? state) constructor overload, storing it as AsyncState rather than configuring continuation behavior

var tcs = new TaskCompletionSource<TReply>(TaskCreationOptions.RunContinuationsAsynchronously);

When SetResult() is called:

  • Continuations run synchronously on the handler thread
  • If a continuation sends another message to the same Agent via Tell(), that message is queued
  • The continuation blocks waiting for the queued message's result
  • The queued message can't be processed because the ActionBlock handler is still executing SetResult()
  • Deadlock

Reproduction

The bug manifests when:

  • Using libraries like LanguageExt that chain async operations via Bind/Map
  • A continuation from one Agent message attempts to call Tell() on the same Agent
  • Intermittent based on continuation chain structure at runtime

Environment

.NET 9.0
Dbosoft.Functional (latest)
Observed when used with YaNco SAP RFC library

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions