environs/config: Validate mutates the config passed to it
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
Canonical Juju |
Expired
|
Low
|
Unassigned |
Bug Description
config.Validate() mutates the config object passed to it.
This is a serious problem as it may not have exclusive ownership of the config object. Consider this code
func (obs *EnvironObserver) loop() error {
for {
}
if err != nil {
}
if err != nil {
}
}
}
The EnvironObserver waits for the environment config to change, then it asks it's state object for the config, passes that to environs.New and then updates it's copy of the environment.
However, environs.New calls down a bunch of places then ends up calling config.Validate to check that the config it was passed was in fact valid. At the bottom of validate there is this line
cfg.defined = ProcessDeprecat
return nil
}
which _updates_ the defined values inside the config. Which is a race because the the EnvironObserver does not own the reference to the st.config object, so it cannot safely update portions of it as config.Config is not defined to be thread safe.
But, it gets worse. If obs.st.
tags: | added: race-condition tech-debt |
Changed in juju-core: | |
status: | New → Triaged |
importance: | Undecided → Medium |
Changed in juju-core: | |
status: | Triaged → In Progress |
assignee: | nobody → Dave Cheney (dave-cheney) |
Changed in juju-core: | |
assignee: | Dave Cheney (dave-cheney) → nobody |
status: | In Progress → Triaged |
Changed in juju-core: | |
milestone: | none → 2.0.0 |
affects: | juju-core → juju |
Changed in juju: | |
milestone: | 2.0.0 → none |
milestone: | none → 2.0.0 |
Changed in juju: | |
milestone: | 2.0.0 → 2.0.1 |
Changed in juju: | |
milestone: | 2.0.1 → none |
AFAICS the EnvironConfig in play here is fresh from the API, and no references are stored anywhere else: in what sense is it not owned by the EnvironObserver at that point?
(That's not to say there aren't a bunch of things wrong there, but I don't see the data race...)