peter-toth commented on code in PR #57285:
URL: https://github.com/apache/spark/pull/57285#discussion_r3639196967


##########
core/src/main/scala/org/apache/spark/deploy/security/HadoopDelegationTokenManager.scala:
##########
@@ -226,24 +261,35 @@ private[spark] class HadoopDelegationTokenManager(
    *
    * @return Credentials containing the new tokens.
    */
-  private def obtainTokensAndScheduleRenewal(ugi: UserGroupInformation): 
Credentials = {
-    ugi.doAs(new PrivilegedExceptionAction[Credentials]() {
-      override def run(): Credentials = {
-        val (creds, nextRenewal) = obtainDelegationTokens()
-
-        // Calculate the time when new credentials should be created, based on 
the configured
-        // ratio.
-        val now = System.currentTimeMillis
-        val ratio = sparkConf.get(CREDENTIALS_RENEWAL_INTERVAL_RATIO)
-        val delay = (ratio * (nextRenewal - now)).toLong
-        logInfo(log"Calculated delay on renewal is ${MDC(LogKeys.DELAY, 
delay)}," +
-          log" based on next renewal ${MDC(LogKeys.NEXT_RENEWAL_TIME, 
nextRenewal)}" +
-          log" and the ratio ${MDC(LogKeys.CREDENTIALS_RENEWAL_INTERVAL_RATIO, 
ratio)}," +
-          log" and current time ${MDC(LogKeys.CURRENT_TIME, now)}")
-        scheduleRenewal(delay)
-        creds
+  private def obtainTokensAndScheduleRenewal(): Credentials = {
+    val (creds, nextRenewal) = if (hasKerberosCredentials) {
+      val freshUGI = doLogin()
+      val currentUser = UserGroupInformation.getCurrentUser()
+      val result = freshUGI.doAs(new PrivilegedExceptionAction[(Credentials, 
Long)]() {
+        override def run(): (Credentials, Long) = {
+          obtainDelegationTokens()
+        }
+      })
+      if (!currentUser.equals(freshUGI)) {
+        FileSystem.closeAllForUGI(freshUGI)
       }
-    })
+      result
+    } else if (sparkConf.get(CREDENTIALS_DIRECT_PROVIDERS_ENABLED)) {
+      obtainDelegationTokens(isolateFailures = true)

Review Comment:
   **Finding 7.** On this renewal path, `obtainDelegationTokens(isolateFailures 
= true)` catches every provider exception (line 199) and returns `None` for the 
failed provider. If *all* providers fail (e.g. the IdP is transiently 
unreachable at startup), `nextRenewal` folds to `Long.MaxValue`, so the `delay` 
computed just below (line 286) is effectively infinite and `scheduleRenewal` 
won't re-run for ~centuries. And since nothing throws, `updateTokensTask`'s 
`catch` — which would otherwise reschedule after 
`CREDENTIALS_RENEWAL_RETRY_WAIT` — never fires. Net: executors receive empty 
credentials and there's no recovery short of a driver restart. The Kerberos 
path avoids this because it doesn't isolate, so a failure propagates and gets 
retried.
   
   Note `nextRenewal == Long.MaxValue` is also the legitimate "providers 
succeeded but reported no expiry" case, so keying a retry off the delay alone 
would over-fire. Cleaner to have the isolate path signal that a failure 
actually occurred (e.g. count the caught exceptions) and, when that count is > 
0, schedule `CREDENTIALS_RENEWAL_RETRY_WAIT` instead of the computed delay.
   



-- 
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