Skip to content

Fix semaphore leak in RabbitMqChannelAgent.EnsureInitiated()#2069

Merged
jeremydmiller merged 1 commit intoJasperFx:mainfrom
smatushonok:fix/semaphore-leak-in-ensure-initiated
Jan 29, 2026
Merged

Fix semaphore leak in RabbitMqChannelAgent.EnsureInitiated()#2069
jeremydmiller merged 1 commit intoJasperFx:mainfrom
smatushonok:fix/semaphore-leak-in-ensure-initiated

Conversation

@smatushonok
Copy link
Copy Markdown
Contributor

Summary

Fix a deadlock caused by a semaphore not being released in EnsureInitiated() when the channel was already initialized by a concurrent call.

Problem

When multiple concurrent PublishAsync calls hit a cold (uninitialized) sender:

  1. All calls pass the first Channel is not null check
  2. First call acquires the semaphore, initializes the channel, releases semaphore
  3. Second call acquires the semaphore, sees channel is now initialized, returns without releasing the semaphore
  4. Remaining calls wait forever on the semaphore

Reproduction

await app.StartAsync();
var bus = scope.ServiceProvider.GetRequiredService<IMessageBus>();

// This deadlocks - only ~2 of 5 messages complete
var tasks = Enumerable.Range(1, 5)
    .Select(id => bus.PublishAsync(id).AsTask())
    .ToArray();
await Task.WhenAll(tasks);

The second null check after acquiring the semaphore returned without
releasing the lock, causing concurrent calls to deadlock.

Reproduction scenario:
- Multiple parallel PublishAsync calls on a cold sender
- First call acquires semaphore and initializes channel
- Second call acquires semaphore, sees channel is initialized,
  returns WITHOUT releasing the semaphore
- Remaining calls wait forever on the semaphore

Fix: Release the semaphore before the early return.
@jeremydmiller jeremydmiller merged commit 92e1c22 into JasperFx:main Jan 29, 2026
1 check passed
This was referenced Feb 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants