L. C. Hsieh created SPARK-60222:
-----------------------------------

             Summary: Keep task completion listeners on the completing thread 
when another thread invokes listeners
                 Key: SPARK-60222
                 URL: https://issues.apache.org/jira/browse/SPARK-60222
             Project: Spark
          Issue Type: Bug
          Components: Spark Core
    Affects Versions: 5.0.0
            Reporter: L. C. Hsieh


TaskContextImpl runs task listeners on one thread at a time, tracked by 
listenerInvocationThread. In two cases, the completion listeners do not run on 
the thread that completes the task:

1. When another thread is invoking listeners as the task completes, 
markTaskCompleted returns without running any completion listener. For example, 
Task.kill calls markInterrupted on the kill thread, and if an interrupt 
listener throws, markTaskFailed runs the failure listeners on that thread. The 
completion listeners are then left until some other thread adds a listener, or 
skipped entirely. The task can then reach cleanUpAllAllocatedMemory while 
resources that the completion listeners would release are still in use. The 
ErrorNotifier doc and a StreamingShuffleSuite test describe this race.
2. When a listener throws, invokeListeners clears listenerInvocationThread 
while markTaskFailed runs the failure listeners, and reclaims it afterwards. 
Another thread that adds a listener in between can take over running the 
pending listeners, possibly concurrently with this thread.

Failure listeners that another thread queues while a thread runs the completion 
listeners, and completion listeners queued while a thread runs failure 
listeners after completion, are also dropped.

This matters for helper threads that the completion listeners stop and wait 
for, such as the pipelined Python UDF writer (SPARK-60113): if the helper 
thread adds a listener lazily at such a moment, it ends up running the listener 
that waits for itself.

The proposed fix keeps the completion listeners on the completing thread: 
markTaskCompleted waits for another thread invoking listeners and takes the 
invocation over directly, failure listeners run inside the current invocation 
when a listener throws, and a thread runs the listeners left to it before it 
releases the invocation. This was first done in apache/spark#59332 and split 
out of it during review.




--
This message was sent by Atlassian Jira
(v8.20.10#820010)

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to