Skip to content

Keep a sub-proxy's returner config out of the shared load (#70219) - #70220

Open
ggiesen wants to merge 1 commit into
saltstack:3008.xfrom
ggiesen:fix-deltaproxy-shared-load-ret
Open

Keep a sub-proxy's returner config out of the shared load (#70219)#70220
ggiesen wants to merge 1 commit into
saltstack:3008.xfrom
ggiesen:fix-deltaproxy-shared-load-ret

Conversation

@ggiesen

@ggiesen ggiesen commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

Stops one deltaproxy sub-proxy's return configuration leaking onto its siblings.

What issues does this PR fix?

Fixes #70219

Root cause

handle_payload hands the same publish-load dict to the control proxy and to every sub-proxy the job matched -- there is no copy. thread_return then merged the sub-proxy's own returner setting back into it:

if isinstance(opts.get("return"), str):
    if data["ret"]:
        data["ret"] = ",".join((data["ret"], opts["return"]))
    else:
        data["ret"] = opts["return"]

With multiprocessing: False every sub-proxy's job runs as a thread in the one salt-proxy process, so they share that dict and whichever sub-proxy ran first stamped its configuration onto the ones that ran after it. With the default multiprocessing: True each job is forked, so the mutation stayed process-local and nothing leaked -- but multiprocessing: False is what a proxy driving a real device needs, since a live NETCONF/SSH session cannot be forked.

Keeping the merge in a local fixes it. thread_multi_return only reads data["ret"] and is left alone.

Previous Behavior

A sub-proxy with no returner configured sent its job return to another sub-proxy's returner, whenever a job matched more than one sub-proxy.

New Behavior

Each sub-proxy uses only its own return configuration.

Merge requirements satisfied?

  • Docs
  • Changelog
  • Tests written/updated

Tests written?

Yes. A unit test in tests/pytests/unit/metaproxy/test_deltaproxy.py drives thread_return twice against one shared load, first as a sub-proxy that has a returner configured and then as one that does not, asserting the shared load is never written to. It fails against unmodified 3008.x, where the second sub-proxy picks up some_returner.

Verified against a live deltaproxy on 3008.2 with three sub-proxies and a returner configured on minion1 only. Instrumenting thread_return shows all three sharing one load object:

before

id=minion1 opts_return='bogus_returner_xyz' data_ret=''                   data_id=130622793244416
id=minion3 opts_return=None                 data_ret='bogus_returner_xyz' data_id=130622793244416
id=minion2 opts_return=None                 data_ret='bogus_returner_xyz' data_id=130622793244416

after

id=minion1 opts_return='bogus_returner_xyz' data_ret='' data_id=134345401241600
id=minion2 opts_return=None                 data_ret='' data_id=134345401241600
id=minion3 opts_return=None                 data_ret='' data_id=134345401241600

minion1 still uses its own returner; its siblings are no longer contaminated.

Commits signed with GPG?

No

…70219)

handle_payload hands the same publish-load dict to the control proxy and
to every sub-proxy the job matched. thread_return then merged this
sub-proxy's opts["return"] back into data["ret"], writing it onto the
dict the next sub-proxy is about to read.

With multiprocessing: False every sub-proxy's job runs as a thread in
the one salt-proxy process, so whichever ran first stamped its returner
configuration onto the ones after it, and a sub-proxy with no returner
of its own sent its job return to another sub-proxy's returner. With the
default multiprocessing: True each job is forked, so the mutation stayed
process-local and nothing leaked -- but multiprocessing: False is what a
proxy driving a real device needs, a live NETCONF/SSH session not being
forkable.

Keep the merge in a local instead. thread_multi_return only reads
data["ret"] and is left alone.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

test:full Run the full test suite

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: deltaproxy leaks one sub-proxy's return configuration onto its siblings via the shared publish load

2 participants