Defect code:
token = _singleWriterMutex.TryWait(options: WaitOptions.NoDelay);
if (!token.Success)
{
if (PushToBacklog(message, onlyIfExists: !ALWAYS_USE_BACKLOG_IF_CANNOT_GET_SYNC_LOCK))
return new ValueTask<WriteResult>(WriteResult.Success); // queued counts as success
...
}
...
if (!flush.IsCompletedSuccessfully)
{
...
return CompleteWriteAndReleaseLockAsync(token, flush, message, lockTaken);
}
Scenario:
Thread A:
await subscriber.PublishAsync("channel-1", 1);
Thread B:
await Task.WhenAll(subscriber.PublishAsync("channel-2", 2), subscriber.PublishAsync("channel-2", 3));
- Thread A try to publish message
1
- Thread A takes the lock(_singleWriterMutex) first.
- Thread B try to publish message
2
- Thread B cannot take the lock, send to backlog.
- Thread B create the backlog, and start the background processing.
- Thread B returns, since
queued counts as success.
- Thread A finish the write message
1, release the lock.
- Thread B try to publish message
3
- Thread B takes the lock.
- Thread B finish the write message
3, release the lock.
- The backlog takes the lock.
- The backlog write message
2.
Then, finally we get following result:
Channel-1: 1
Channel-2: 3, 2
Defect code:
Scenario:
Thread A:
Thread B:
12queued counts as success.1, release the lock.33, release the lock.2.Then, finally we get following result:
Channel-1:
1Channel-2:
3, 2