dongjoon-hyun commented on code in PR #58574:
URL: https://github.com/apache/spark/pull/58574#discussion_r3972283837


##########
core/src/main/scala/org/apache/spark/SparkContext.scala:
##########
@@ -337,6 +346,12 @@ class SparkContext(config: SparkConf) extends Logging {
    */
   def hadoopConfiguration: Configuration = _hadoopConfiguration
 
+  // The CredentialProviderLoader from the OIDC selection phase, reused by the 
credential
+  // resolution phase so providers are initialized exactly once. Null if OIDC 
is disabled or

Review Comment:
   Nit: this comment still says "Null if OIDC is disabled or before 
initialization"; it is now `None` (also in local mode).



##########
core/src/main/scala/org/apache/spark/deploy/security/UserCredentialManager.scala:
##########
@@ -300,7 +278,12 @@ private[spark] class UserCredentialManager(
               log"returned null; skipping.")
           } else {
             credentialMap.put(scheme, credential)
-            activeProviders += provider
+
+            // Fallback wiring for a provider that actually resolved a 
credential. Idempotent
+            // with the selection phase (guarded by !contains); only on 
initial acquisition.
+            if (applyProperties) {
+              applyResolvedProviderProperties(scheme, provider)

Review Comment:
   This fallback runs inside the per-scheme `catch { case e: Exception => ... 
}` below, after `credentialMap.put` and before the expiry update. If 
`additionalSparkProperties()` throws (the case the selection-phase test covers 
with `AnotherFakeCredentialProvider.throwOnProperties`), the credential stays 
in the map but the `earliestExpiry` update is skipped, and the log says "Failed 
to resolve credentials for scheme ... Skipping this provider", which is not 
what happened. The renewal delay is then computed without that credential's 
expiry.
   
   The pre-PR loop isolated `additionalSparkProperties()` with its own 
`NonFatal` catch. Could we wrap this call (or `applyDeclaredProperties` itself) 
in its own `try`/`NonFatal` that only logs, or move it after the expiry update? 
A `start()`-level test with a throwing provider would lock this in; the 
existing one only covers `applyProviderProperties`.



##########
core/src/main/scala/org/apache/spark/scheduler/cluster/CoarseGrainedSchedulerBackend.scala:
##########
@@ -697,9 +697,18 @@ class CoarseGrainedSchedulerBackend(scheduler: 
TaskSchedulerImpl, val rpcEnv: Rp
   override def stop(): Unit = {
     reviveThread.shutdownNow()
     cleanupService.foreach(_.shutdownNow())
-    stopExecutors()
-    stopTokenManager()
-    stopUserCredentialManager()
+    // Ensure the token and user-credential managers are always stopped, even 
if stopExecutors()
+    // throws (e.g. the StopExecutors ask times out during shutdown, which
+    // KubernetesClusterSchedulerBackend.stop already anticipates). Otherwise 
the
+    // UserCredentialManager renewal thread would be left running while 
SparkContext.stop()
+    // closes the shared CredentialProviderLoader, causing the renewal task to 
fail repeatedly
+    // against an already-closed loader.
+    try {
+      stopExecutors()
+    } finally {
+      stopTokenManager()

Review Comment:
   Nit: if `stopTokenManager()` throws here, `stopUserCredentialManager()` is 
skipped, which is the same shape of problem this block fixes for 
`stopExecutors()`. Wrapping each of the two in `Utils.tryLogNonFatalError` 
would make them independent.



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