Skip to content

Conversation

@RichardD2
Copy link
Contributor

Description

The WeakEventHandlerBase needs to protect all access to the _handlers list with the _lock to avoid state corruption.

Additionally, the handlers should be executed whilst the lock is not held, to avoid deadlocks if a handler attempts to call a method on the event object.

Type of Change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update
  • Other (please specify):

Checklist

  • The PR is submitted to the correct branch (main).
  • My code follows the project's coding style. (.editorconfig)
  • I have commented my code, particularly in hard-to-understand areas and public interfaces.
  • I have added or updated tests for the changes I made.
  • All new and existing tests passed.
  • I have updated the documentation where applicable.

Testing Instructions

With the current code, a handler which attempts to modify the event object could result in corrupted state. At the very least, any attempt to modify the handlers list from a handler would result in an InvalidOperationException:

Collection was modified; enumeration operation may not execute.
   at System.Collections.Generic.List`1.Enumerator.MoveNextRare()
   at System.Collections.Generic.List`1.Enumerator.MoveNext()
   at WeakEventBase.PublishAsync(List`1 args, CancellationToken cancellationToken)

The simplistic solution is to wrap every access to the _handlers list in the lock. However, this would then result in a deadlock, since the handler is executed whilst the lock is already held, and the SemaphoreSlim does not support reentrancy.

Therefore, the actual solution is to also ensure that the handlers are invoked whilst the lock is not held. This involves taking a copy of the handlers list within the lock, and then operating on it outside of the lock.

…dlers are called whilst the lock is not held. Add a unit test to validate.
@Seramis Seramis merged commit 44110e0 into ByteAether:main Jul 1, 2025
3 checks passed
@Seramis
Copy link
Member

Seramis commented Jul 1, 2025

Thank you for this contribution and beautiful work, @RichardD2!

I very much appreciate that.

@Seramis
Copy link
Member

Seramis commented Jul 6, 2025

@RichardD2, I've now released version 1.0.3, that now has this fix in place.

Thank you once more!

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