Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: Collection was modified exception #331

Merged
merged 1 commit into from
Aug 22, 2019
Merged

Fix: Collection was modified exception #331

merged 1 commit into from
Aug 22, 2019

Conversation

theramis
Copy link
Contributor

@theramis theramis commented Aug 22, 2019

Problem

We are using wiremock as part of our tests and we found that if we have tests running in parallel we sometimes get an error when calling the FindLogEntries method.

Error

System.InvalidOperationException: Collection was modified; enumeration operation may not execute.

Potential Solution

This is my quick attempt at fixing the above issue. By convert the collection into a new list it shouldn't throw an error if the LogEntries collection is updated.
From a quick google around the ToList method itself isn't thread safe either though. So its possible that while the ToList method is creating a copy, it fails due to the original collection getting changed.

Thoughts?
@StefH

@codecov
Copy link

codecov bot commented Aug 22, 2019

Codecov Report

Merging #331 into master will not change coverage.
The diff coverage is 0%.

Impacted file tree graph

@@           Coverage Diff           @@
##           master     #331   +/-   ##
=======================================
  Coverage   80.08%   80.08%           
=======================================
  Files         111      111           
  Lines        4423     4423           
=======================================
  Hits         3542     3542           
  Misses        881      881
Impacted Files Coverage Δ
...WireMock.Net/Server/FluentMockServer.LogEntries.cs 16.66% <0%> (ø) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 19ee3c6...f80debc. Read the comment docs.

Copy link
Collaborator

@StefH StefH left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you take a look ?

@@ -39,7 +39,7 @@ public IEnumerable<LogEntry> FindLogEntries([NotNull] params IRequestMatcher[] m
{
var results = new Dictionary<LogEntry, RequestMatchResult>();

foreach (var log in _options.LogEntries)
foreach (var log in _options.LogEntries.ToList())
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's even better to just use the property LogEntries here (that property is already made safe...)

Also in the DeleteLogEntry() method, it's safer to use the LogEntries property.

Copy link
Contributor Author

@theramis theramis Aug 22, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's even better to just use the property LogEntries here (that property is already made safe...)

Adding/Removing/Setting/Clearing is thread safe for the LogEntries property (due to https://github.com/WireMock-Net/WireMock.Net/blob/master/src/WireMock.Net/Util/ConcurrentObservableCollection.cs) but enumerating is not.

In my case we have thread 1 calling FindLogEntries
and thread 2 calling a mocked http api.

Since the foreach loop above does not hold a lock, the log entry for the call made by thread 2 is added to the LogEntries property. This causes the enumerator in the foreach loop to throw an exception.

I hope that explanation makes sense?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also in the DeleteLogEntry() method, it's safer to use the LogEntries property

Yup in that method LogEntries is perfect, since the Remove method on LogEntries is thread safe.

@StefH
Copy link
Collaborator

StefH commented Aug 22, 2019

Thanks for this PR, can you take a look at my comments?

@StefH StefH added the bug label Aug 22, 2019
@StefH StefH merged commit fc64c5f into WireMock-Net:master Aug 22, 2019
@gregoks
Copy link

gregoks commented Sep 1, 2019

hi guys,

I'm using version 1.0.30-ci11848 and still getting this error:

HttpStatusCode set to 500 System.InvalidOperationException: Collection was modified; enumeration operation may not execute. at System.Collections.Generic.List1.Enumerator.MoveNextRare() at System.Linq.Enumerable.WhereEnumerableIterator1.ToList() at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source) at WireMock.Owin.WireMockMiddleware.LogRequest(LogEntry entry, Boolean addRequest) at WireMock.Owin.WireMockMiddleware.InvokeInternal(HttpContext ctx) at WireMock.Owin.GlobalExceptionMiddleware.InvokeInternal(HttpContext ctx)

Is it the same as in this bug?

@StefH
Copy link
Collaborator

StefH commented Sep 1, 2019

@gregoks A new fix is required I think.
I will check,.

@StefH
Copy link
Collaborator

StefH commented Sep 1, 2019

@gregoks Can you please try:
WireMock.Net.1.0.31-ci-11865

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants