Repository navigation
Conversation
|
@HyukjinKwon would you be able to take a look? This should fix https://issues.apache.org/jira/browse/SPARK-50118 at which you had a stab a while back but had to be reverted. Thank you! |
spark-test
left a comment
There was a problem hiding this comment.
Review summary
The executor-side fix is sound. Tying factories to IsolatedSessionState.cleanup() behind the existing eviction refcount stops a session's daemon, pooled workers and monitor thread before its directory is deleted, and a later task for the same UUID gets a fresh factory. PythonWorkerFactory.stop() now also ends the idle-worker monitor thread.
Two defects remain. The new removal path makes a late destroyPythonWorker/releasePythonWorker (reachable from PythonRunner.MonitorThread) silently drop its worker instead of closing it, which contradicts the description's guarantee for late workers. The new UDTF eviction test's cleanup also cannot reach the driver-owned planner factory that the test itself creates. A question for the author about driver-side planner cleanup follows.
Cross-cutting observations
- The leaked daemon in the new UDTF eviction test and the uncleaned driver planner factories in Spark Connect sessions have the same cause. Driver-owned factories created by PythonPlannerRunner can currently only be removed by SparkEnv.stop(), because the new session cleanup deliberately skips them and ArtifactManager has no hook for them.
Separation: The test cleanup can be fixed on its own with a narrow removal helper. Whether production session close should also use such a path is the author's decision under the driver-planner question. This pattern does not merge their repairs or settle that decision.
Findings
2 total: 0 P0, 0 P1, 1 P2, 1 P3.
Non-blocking (P2)
- Late destroy/release after factory removal silently drops the worker —
core/src/main/scala/org/apache/spark/SparkEnv.scala:404— see inline.
Nit (P3)
- UDTF eviction test cleanup cannot remove the driver-owned planner factory it creates —
sql/core/src/test/scala/org/apache/spark/sql/execution/python/PythonUDTFSuite.scala:206— see inline.
Decision challenges
Driver-owned planner factories are never cleaned on session close, despite the PR description
The PR description says driver-side planner factories are cleaned when the session's ArtifactManager closes. In the diff, removePythonWorkerFactories explicitly skips driverOwned keys, every PythonPlannerRunner factory is now driverOwned = true, and ArtifactManager is unchanged with no reference to Python worker factories. Apart from SparkEnv.stop(), nothing removes these factories. So on a Spark Connect driver, every session that runs a UDTF analyze() or a Python data source planner with the daemon keeps its planner daemon and pooled workers after the session closes. In local mode that daemon also keeps running in the session directory that executor cleanup deletes, and a later planner call for the same session reuses it. This is the shape the PR fixes for executor factories. Did you intend to add ArtifactManager-driven cleanup of driver-owned factories in this PR? Or should the description drop that claim and record driver planner cleanup as a follow-up?
Generated by Omnigent on Databricks
|
Thanks, I've addressed the comments |
What changes were proposed in this pull request?
The PR ties Python worker factories to the session lifecycle:
ArtifactManagercloses.This prevents reuse of daemons whose working directory was deleted and avoids per-session process/thread leaks.
Why are the changes needed?
This addresses:
SPARK-54055: Spark Connect sessions leak pyspark UDF daemon processes and threads
SPARK-50118: Spark removes working directory while Python UDF runs. There was an attempt in the past to fix this, but it was eventually reverted.
Spark caches a separate
PythonWorkerFactoryfor each combination of Python configuration and session artifact UUID. Each factory may own a long-live Python daemon, reusable Python workers, an idle-worker monitor thread.For session-isolated workloads, those processes are launched with the session’s artifact directory as their working directory, for example:
We can hit the following scenario:
PythonWorkerFactory, its daemon starts inside the session directory.IsolatedSessionState.cleanup()deletes the session directory and classloader resources.If the same session is used again, Spark may reuse that factory and daemon ,which can lead to issues.
Even if the session is never used again, every evicted session can leave behind resources (daemon/worker processes, monitor thread) forever.
Does this PR introduce any user-facing change?
This fixes bugs/leaks.
How was this patch tested?
Unit and integration tests.
Was this patch authored or co-authored using generative AI tooling?
Generated-by: codex-cli 0.161.0