ulysses-you commented on code in PR #57329:
URL: https://github.com/apache/spark/pull/57329#discussion_r3627550829


##########
core/src/main/scala/org/apache/spark/scheduler/TaskSetManager.scala:
##########
@@ -1247,6 +1318,11 @@ private[spark] class TaskSetManager(
           // that the task is not running, and it is NetworkFailure rather 
than TaskFailure.
           case _ => !info.launching
         }
+        // Grow the CPUs of the retry when a running task's executor died of a 
JVM heap OOM. See
+        // the SparkOutOfMemoryError branch in handleFailedTask for the 
non-fatal counterpart.
+        if (oomRetryCpusIncrement > 0 && !isBarrier && isOomExit && 
exitCausedByApp) {

Review Comment:
   Fixed in 136abaa041a. `isOom` now walks a bounded cause chain instead of 
inspecting only the top-level exception, reusing 
`spark.executor.killOnFatalError.depth` as the bound (the same depth 
`Executor.isFatalError` uses to find a fatal error in a wrapped exception), 
with a top-level class-name fallback when the throwable was not preserved:
   
   ```scala
   private def isOom(ef: ExceptionFailure, depthToCheck: Int): Boolean = {
     ef.exception match {
       case Some(t) => causedByOom(t, depthToCheck)
       case None =>
         ef.className == classOf[OutOfMemoryError].getName ||
           ef.className == classOf[SparkOutOfMemoryError].getName
     }
   }
   
   @scala.annotation.tailrec
   private def causedByOom(t: Throwable, depthToCheck: Int): Boolean = {
     if (depthToCheck <= 0) false
     else t match {
       case _: OutOfMemoryError => true // SparkOutOfMemoryError is a subclass
       case e if e.getCause != null => causedByOom(e.getCause, depthToCheck - 1)
       case _ => false
     }
   }
   ```
   
   This recognizes both cases you raised: a wrapped `SparkOutOfMemoryError` 
(non-fatal, no executor-loss fallback) now grows the retry, and a wrapped JVM 
`OutOfMemoryError` sent as FAILED before the executor exits is recognized on 
the FAILED path so the later OOM exit being skipped by the `info.running` guard 
no longer loses the classification. Added two tests: `wrapped 
SparkOutOfMemoryError increments numOomRetries` and `wrapped JVM 
OutOfMemoryError FAILED before executor loss increments once` (the latter also 
asserts the subsequent executor loss does not double-count).
   
   One accepted limitation: if the throwable is not preserved (`preserveCause = 
false`) the fallback only inspects the top-level class name, so a wrapped OOM 
whose throwable was dropped is not recognized. Carrying an explicit OOM flag 
from the executor would close that gap but requires a wire/protocol change; 
happy to pursue that separately if you think it is worth it.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


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

Reply via email to