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

Bugfix: Make the Put on the SimpleDnsCache idempotent #1222

Merged
merged 1 commit into from
Aug 9, 2015
Merged

Bugfix: Make the Put on the SimpleDnsCache idempotent #1222

merged 1 commit into from
Aug 9, 2015

Conversation

evertmulder
Copy link
Contributor

Bugfix for the exception: itemwith the same key has already been added.
Make the Put on the SimpleDnsCache idempotent when a same host is
resolved.

Bugfix for the exception: itemwith the same key has already been added.
Make the Put on the SimpleDnsCache idempotent when a same host is
resolved.
@rogeralsing
Copy link
Contributor

Is this really thread safe?
This seems to be used from a system extension (DnsExt : IOExtension) which makes me think it is a shared resource.
And the implementation is based on mutability, so shared mutable state unless I'm reading this wrong.

cc @akkadotnet/developers

@rogeralsing
Copy link
Contributor

This is related but not part of the actual PR:

        internal void Put(Dns.Resolved r, long ttl)
        {
            var c = _cache.Value;
            if (!_cache.CompareAndSet(c, c.Put(r, ttl)))
                Put(r, ttl);
        }

the Put method use an atomic reference to compare and set.. but the values that are compared are the same instance, it's the same c that is compared to itself.

            public Cache Put(Dns.Resolved answer, long ttl)
            {
                var until = _clock() + ttl;
                _queue.Add(new ExpiryEntry(answer.Name, until));
                _cache.Add(answer.Name, new CacheEntry(answer, until));
                return this; //<----------------------- returns itself.
            }

c and c.Put(..) refers to the same thing, and thus the compare and set will always succeed.

The code consuming this is based on immutability and the SimpleDnsCache is based on mutability..

IMO, SimpleDnsCache needs to be rewritten or the consuming code will be subject to race conditions...

@rogeralsing
Copy link
Contributor

The corresponding method in Scala looks like this:

    def put(answer: Resolved, ttlMillis: Long): Cache = {
      val until = clock() + ttlMillis

      new Cache(
        queue + new ExpiryEntry(answer.name, until),
        cache + (answer.name -> CacheEntry(answer, until)),
        clock)
    }

Which clearly returns a new instance of the cache.

@rogeralsing
Copy link
Contributor

It seems that SimpleDnsManager is and actor and the only consumer of this extension. so it might be safe for now. but it is still flaky to have an extension that is not thread safe IMO.

@evertmulder
Copy link
Contributor Author

Yes the code does not look Thread Safe and the implementation looks a bit different than the Scala version. Also the Datetime.Now should use the UtcNow I think. Perhaps some more people can have a look at this class.

rogeralsing added a commit that referenced this pull request Aug 9, 2015
Bugfix: Make the Put on the SimpleDnsCache idempotent
@rogeralsing rogeralsing merged commit aa45d71 into akkadotnet:dev Aug 9, 2015
@rogeralsing
Copy link
Contributor

As this PR is better than the current code, I'm merging this.
But I will open an issue for a rewrite of the SimpleDnsCache to follow the Scala version.

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