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

Avoid possible race condition using locks #6850

Closed
wants to merge 13 commits into from

Conversation

Pushpalanka
Copy link
Contributor

Why the changes in this PR are needed?

to address #6849

What are the changes in this PR?

Add locks when reading and writing the bundle plugin configuration.

No tests are added, as not sure exactly on how to write a test for this. The issue is experienced when checking for race conditions while using bundle plugin status listeners while using OPA as a library.

@@ -157,7 +157,10 @@ func (p *Plugin) Reconfigure(ctx context.Context, config interface{}) {
// Look for any bundles that have had their config changed, are new, or have been removed
newConfig := config.(*Config)
newBundles, updatedBundles, deletedBundles := p.configDelta(newConfig)

p.mtx.Lock()
Copy link
Contributor

Choose a reason for hiding this comment

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

There already is a p.cfgMtx that is held for this purpose further above

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, thanks for pointing out.

@Pushpalanka Pushpalanka closed this Jul 5, 2024
@Pushpalanka Pushpalanka reopened this Jul 11, 2024
@Pushpalanka Pushpalanka marked this pull request as draft July 11, 2024 09:28
@Pushpalanka Pushpalanka force-pushed the race-condition branch 2 times, most recently from 57f8f05 to 5c620d6 Compare July 11, 2024 09:37
@Pushpalanka Pushpalanka marked this pull request as ready for review July 11, 2024 15:16
@@ -62,7 +62,7 @@ type Plugin struct {
downloaders map[string]Loader
logger logging.Logger
mtx sync.Mutex
cfgMtx sync.Mutex
cfgMtx sync.RWMutex
Copy link
Member

Choose a reason for hiding this comment

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

We need to hold the write lock while updating the config. Also if you could look at the test failures that would be great. Thanks.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks. I have addressed it.
Could you please have a look?

@Pushpalanka Pushpalanka force-pushed the race-condition branch 4 times, most recently from ae231b0 to 8d9ff08 Compare July 17, 2024 18:50
Copy link
Member

@ashutosh-narkar ashutosh-narkar left a comment

Choose a reason for hiding this comment

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

@Pushpalanka the changes seem ok. There are places where previously atomic operations are no longer atomic. So we need to be careful about the impact of the change.

p.cfgMtx.Lock()
p.config = *parsedConfig
p.cfgMtx.Unlock()

Copy link
Member

Choose a reason for hiding this comment

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

Why do need to hold the lock during plugin instantiation?

Copy link
Contributor Author

@Pushpalanka Pushpalanka Jul 21, 2024

Choose a reason for hiding this comment

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

Thanks for raising this! Was carried away by the line 74 parsedConfig.Bundles as it reads the Bundles from the config. But yes we don't need this at initiation.

p.cfgMtx.RLock()
bundles := p.config.Bundles
p.cfgMtx.RUnlock()

Copy link
Member

Choose a reason for hiding this comment

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

Currently the below operation is performed atomically. Do we know the consequences of changing that behavior?

Copy link
Contributor

@mjungsbluth mjungsbluth Jul 19, 2024

Choose a reason for hiding this comment

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

This needs to be changed (be atomic for the iteration).

Copy link

netlify bot commented Jul 21, 2024

Deploy Preview for openpolicyagent ready!

Name Link
🔨 Latest commit 9b945de
🔍 Latest deploy log https://app.netlify.com/sites/openpolicyagent/deploys/669e991efa74c8000924ee67
😎 Deploy Preview https://deploy-preview-6850--openpolicyagent.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

@Pushpalanka Pushpalanka force-pushed the race-condition branch 4 times, most recently from fc89516 to 927bf03 Compare July 22, 2024 14:31
@@ -310,10 +313,14 @@ func (p *Plugin) UnregisterBulkListener(name interface{}) {

// Config returns the plugins current configuration
func (p *Plugin) Config() *Config {
p.cfgMtx.RLock()
defer p.cfgMtx.RUnlock()
Copy link
Member

Choose a reason for hiding this comment

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

We aren't making a copy of the config, so what benefit is the lock giving us here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I am thinking we still need to protect against reading while writes are in-progress.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Just understood the point. Will correct.

Signed-off-by: Pushpalanka Jayawardhana <pushpalanka.jayawardhana@zalando.de>
Signed-off-by: Pushpalanka Jayawardhana <pushpalanka.jayawardhana@zalando.de>
Signed-off-by: Pushpalanka Jayawardhana <pushpalanka.jayawardhana@zalando.de>
Signed-off-by: Pushpalanka Jayawardhana <pushpalanka.jayawardhana@zalando.de>
Signed-off-by: Pushpalanka Jayawardhana <pushpalanka.jayawardhana@zalando.de>
Signed-off-by: Pushpalanka Jayawardhana <pushpalanka.jayawardhana@zalando.de>
Signed-off-by: Pushpalanka Jayawardhana <pushpalanka.jayawardhana@zalando.de>
Signed-off-by: Pushpalanka Jayawardhana <pushpalanka.jayawardhana@zalando.de>
Signed-off-by: Pushpalanka Jayawardhana <pushpalanka.jayawardhana@zalando.de>
Signed-off-by: Pushpalanka Jayawardhana <pushpalanka.jayawardhana@zalando.de>
Signed-off-by: Pushpalanka Jayawardhana <pushpalanka.jayawardhana@zalando.de>
Signed-off-by: Pushpalanka Jayawardhana <pushpalanka.jayawardhana@zalando.de>
Signed-off-by: Pushpalanka Jayawardhana <pushpalanka.jayawardhana@zalando.de>

// Look for any bundles that have had their config changed, are new, or have been removed
newConfig := config.(*Config)
newBundles, updatedBundles, deletedBundles := p.configDelta(newConfig)
p.config = *newConfig
p.cfgMtx.Unlock()
Copy link
Member

Choose a reason for hiding this comment

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

Have you considered the scenario of concurrent calls to Reconfigure? Could it break the following code flow?

What if we keep the existing code here?

p.cfgMtx.RLock()
src := p.config.Bundles[name]
p.cfgMtx.RUnlock()

Copy link
Member

Choose a reason for hiding this comment

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

If the write lock on the config was acquired at this point, won't it affect persistBundle?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I couldn't see a concern with persistBundle as src is read to a new variable and passed. However if we acquire the write lock for the whole method of Reconfigure as in previous comment, then this read lock will be a problem.
Not sure if I understood your concern here.

@ashutosh-narkar
Copy link
Member

@Pushpalanka thanks for the back and forth on this and also for addressing my comments. Dealing with mutexes is tricky and sometimes it's hard to tell if a change can have unintended consequences. So I appreciate your work on this.

@Pushpalanka
Copy link
Contributor Author

@Pushpalanka thanks for the back and forth on this and also for addressing my comments. Dealing with mutexes is tricky and sometimes it's hard to tell if a change can have unintended consequences. So I appreciate your work on this.

Thanks @ashutosh-narkar for your patience and support so far. I am surfing unknown waters here, yet understand this is a tricky and critical code segments I am touching. Feel free to take over as well if this becoming less efficient. :)

@ashutosh-narkar
Copy link
Member

@Pushpalanka thanks for the back and forth on this and also for addressing my comments. Dealing with mutexes is tricky and sometimes it's hard to tell if a change can have unintended consequences. So I appreciate your work on this.

Thanks @ashutosh-narkar for your patience and support so far. I am surfing unknown waters here, yet understand this is a tricky and critical code segments I am touching. Feel free to take over as well if this becoming less efficient. :)

I'll spend sometime looking into this. Thanks for reporting the issue and working on a fix.

@ashutosh-narkar
Copy link
Member

Closing in favor of #6921. Thanks for working on this @Pushpalanka!

@Pushpalanka
Copy link
Contributor Author

Closing in favor of #6921. Thanks for working on this @Pushpalanka!

Thanks a lot @ashutosh-narkar 👍

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.

None yet

3 participants