@@ -58,7 +58,37 @@ class CometShuffleManager(conf: SparkConf) extends ShuffleManager with Logging {
5858 */
5959 private [this ] val taskIdMapsForShuffle = new ConcurrentHashMap [Int , OpenHashSet [Long ]]()
6060
61- private lazy val shuffleExecutorComponents = loadShuffleExecutorComponents(conf)
61+ // Lazy initialization to avoid accessing SparkEnv.get during ShuffleManager construction,
62+ // which can cause hangs when SparkEnv is not fully initialized (e.g., during Hive metastore ops)
63+ // This is only initialized when getWriter/getReader is called (during task execution),
64+ // at which point SparkEnv should be fully available
65+ @ volatile private var _shuffleExecutorComponents : ShuffleExecutorComponents = _
66+
67+ private def shuffleExecutorComponents : ShuffleExecutorComponents = {
68+ if (_shuffleExecutorComponents == null ) {
69+ synchronized {
70+ if (_shuffleExecutorComponents == null ) {
71+ val executorComponents = ShuffleDataIOUtils .loadShuffleDataIO(conf).executor()
72+ val extraConfigs =
73+ conf.getAllWithPrefix(ShuffleDataIOUtils .SHUFFLE_SPARK_CONF_PREFIX ).toMap
74+ // SparkEnv.get should be available when getWriter/getReader is called
75+ // (during task execution), but check for null to avoid hangs
76+ val env = SparkEnv .get
77+ if (env == null ) {
78+ throw new IllegalStateException (
79+ " SparkEnv.get is null during shuffleExecutorComponents initialization. " +
80+ " This may indicate a timing issue with SparkEnv initialization." )
81+ }
82+ executorComponents.initializeExecutor(
83+ conf.getAppId,
84+ env.executorId,
85+ extraConfigs.asJava)
86+ _shuffleExecutorComponents = executorComponents
87+ }
88+ }
89+ }
90+ _shuffleExecutorComponents
91+ }
6292
6393 override val shuffleBlockResolver : IndexShuffleBlockResolver = {
6494 // The patch versions of Spark 3.4 have different constructor signatures:
@@ -253,19 +283,6 @@ class CometShuffleManager(conf: SparkConf) extends ShuffleManager with Logging {
253283
254284object CometShuffleManager extends Logging {
255285
256- /**
257- * Loads executor components for shuffle data IO.
258- */
259- private def loadShuffleExecutorComponents (conf : SparkConf ): ShuffleExecutorComponents = {
260- val executorComponents = ShuffleDataIOUtils .loadShuffleDataIO(conf).executor()
261- val extraConfigs = conf.getAllWithPrefix(ShuffleDataIOUtils .SHUFFLE_SPARK_CONF_PREFIX ).toMap
262- executorComponents.initializeExecutor(
263- conf.getAppId,
264- SparkEnv .get.executorId,
265- extraConfigs.asJava)
266- executorComponents
267- }
268-
269286 def shouldBypassMergeSort (conf : SparkConf , dep : ShuffleDependency [_, _, _]): Boolean = {
270287 // We cannot bypass sorting if we need to do map-side aggregation.
271288 if (dep.mapSideCombine) {
0 commit comments