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

address circular reference in LazyLoader with ThreadLocalProxy #51499

Merged
merged 1 commit into from
Feb 13, 2019

Conversation

mattp-
Copy link
Contributor

@mattp- mattp- commented Feb 5, 2019

What does this PR do?

when lazyLoader was getting instantiated from inside already lazyloaded
modules (ie state), pillar/grain (and probably other) globals were
already populated. In this case they weren't getting dereferenced
properly when wrapped via the NamespacedDict wrapper, causing an
infinite loop. This should fix that scenario.

What issues does this PR fix or reference?

#50655 (comment)

pushing this to see what jenkins has to say

Previous Behavior

Remove this section if not relevant

New Behavior

Remove this section if not relevant

Tests written?

Yes/No

Commits signed with GPG?

Yes/No

Please review Salt's Contributing Guide for best practices.

See GitHub's page on GPG signing for more information about signing commits with GPG.

@mattp- mattp- requested a review from a team as a code owner February 5, 2019 01:12
@dwoz dwoz requested a review from terminalmage February 5, 2019 18:45
@terminalmage
Copy link
Contributor

I think the whole reason was to make the context dicts thread-safe. @smarsching should probably have some input here.

@mattp-
Copy link
Contributor Author

mattp- commented Feb 5, 2019

@thatch45 @terminalmage @smarsching figured out what was going on, pushed a proper fix. Would still appreciate a review but I'm fairly confident this fix is good for merge.

@mattp- mattp- changed the title attempt to address circular reference in LazyLoader with ThreadLocalProxy address circular reference in LazyLoader with ThreadLocalProxy Feb 5, 2019
@mattp- mattp- force-pushed the threading branch 2 times, most recently from 400067a to 45c7994 Compare February 5, 2019 19:13
@terminalmage
Copy link
Contributor

This does make more sense but I'd still appreciate eyes on this from @smarsching.

I'm also kind of worried about what other areas of Salt's code could potentially be affected by similar issues.

@mattp- mattp- force-pushed the threading branch 3 times, most recently from e3adec2 to d18f124 Compare February 5, 2019 20:12
waynew
waynew previously requested changes Feb 5, 2019
Copy link
Contributor

@waynew waynew left a comment

Choose a reason for hiding this comment

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

Minor style change.

I don't know enough about the ThreadLocalProxy to have a good opinion on what's going on with the rest of the change(s). I don't see anything that strikes me as obviously wrong, though.

salt/loader.py Outdated
@@ -35,7 +35,7 @@
import salt.utils.lazy
import salt.utils.odict
import salt.utils.platform
import salt.utils.thread_local_proxy
from salt.utils.thread_local_proxy import ThreadLocalProxy
Copy link
Contributor

Choose a reason for hiding this comment

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

You'll want to move this from import down with the rest of the from (somewhere below line 41).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed

@smarsching
Copy link
Contributor

I am sorry for being so so quiet about this issue, I am currently preoccupied with some other projects.

@mattp Basically, your changes look good to me. I only wondered, why you used

if isinstance(value, ThreadLocalProxy):
    value = ThreadLocalProxy.get_reference(value)

when

value =ThreadLocalProxy.unproxy(value)

is simpler and would achieve nearly the same thing (the only difference is that unproxy also handles the case where a proxy refers to another proxy that eventually refers to a non-proxy object).

On a more general note: I am not quite sure I understand why this issue exists in the first place and whether this is the best way to fix it. From the stack trace, it looks like there is a ThreadLocalProxy that refers to a NamespacedDictWrapper which in turn references the same ThreadLocalProxy.

As far as I understand the problem, this issue appears when a NamespacedDictWrapper is later modified to contain aThreadLocalProxy referencing the same NamespacedDictWrapper.

However, there is one thing, that I do not understand about this: Even without the ThreadLocalProxy, having a NamespacedDictWrapper referencing itself should lead to the same infinite loop, so I must be missing something...

when lazyLoader was getting instantiated from inside already lazyloaded
modules (ie state), pillar/grain (and probably other) globals were
already populated. In this case they weren't getting dereferenced
properly when wrapped via the NamespacedDict wrapper, causing an
infinite loop. This should fix that scenario.

Fixes saltstack#50655 (comment)
@mattp-
Copy link
Contributor Author

mattp- commented Feb 5, 2019

@smarsching no worries, wrt get_reference vs unproxy, it wasn't a conscious choice - I can update that.
wrt how this happens, I think the general problem is:

  • modules.state is loaded, pillar proxy is injected
  • modules.state creates a lazy loader, passes current pillar(proxy to existing context dict) as opts[pillar]
  • that lazyloader doesnt deref, then namespacedict wraps it
  • modules.state is reloaded via lazyloader
  • since _inject_into_mod checks if the value is a ThreadLocalProxy, but not if it is a wrappeddict to a proxy, it is overridden
    ^ I think that is where the loop is created, because this dict wrapper is hiding the encapsulation to do the de-reference. The flow in this code is complicated to say the least, so hopefully my current understanding is correct.
    I've added a regression test and updated to use unproxy. thanks for the input 👍

@dwoz
Copy link
Contributor

dwoz commented Feb 13, 2019

@waynew Are we good here?

@terminalmage terminalmage merged commit 15cf5ee into saltstack:develop Feb 13, 2019
@oeuftete oeuftete mentioned this pull request Nov 21, 2019
1 task
dwoz added a commit that referenced this pull request Dec 5, 2019
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.

6 participants