@@ -223,6 +223,7 @@ class SparkContext(config: SparkConf) extends Logging with ExecutorAllocationCli
223223 private var _listenerBusStarted : Boolean = false
224224 private var _jars : Seq [String ] = _
225225 private var _files : Seq [String ] = _
226+ private var _shutdownHookRef : AnyRef = _
226227
227228 /* ------------------------------------------------------------------------------------- *
228229 | Accessors and public fields. These provide access to the internal state of the |
@@ -517,6 +518,14 @@ class SparkContext(config: SparkConf) extends Logging with ExecutorAllocationCli
517518 _taskScheduler.postStartHook()
518519 _env.metricsSystem.registerSource(new DAGSchedulerSource (dagScheduler))
519520 _env.metricsSystem.registerSource(new BlockManagerSource (_env.blockManager))
521+
522+ // Make sure the context is stopped if the user forgets about it. This avoids leaving
523+ // unfinished event logs around after the JVM exits cleanly. It doesn't help if the JVM
524+ // is killed, though.
525+ _shutdownHookRef = Utils .addShutdownHook(Utils .SPARK_CONTEXT_SHUTDOWN_PRIORITY ) { () =>
526+ logInfo(" Invoking stop() from shutdown hook" )
527+ stop()
528+ }
520529 } catch {
521530 case NonFatal (e) =>
522531 logError(" Error initializing SparkContext." , e)
@@ -1055,7 +1064,7 @@ class SparkContext(config: SparkConf) extends Logging with ExecutorAllocationCli
10551064 /** Build the union of a list of RDDs. */
10561065 def union [T : ClassTag ](rdds : Seq [RDD [T ]]): RDD [T ] = {
10571066 val partitioners = rdds.flatMap(_.partitioner).toSet
1058- if (partitioners.size == 1 ) {
1067+ if (rdds.forall(_.partitioner.isDefined) && partitioners.size == 1 ) {
10591068 new PartitionerAwareUnionRDD (this , rdds)
10601069 } else {
10611070 new UnionRDD (this , rdds)
@@ -1481,6 +1490,9 @@ class SparkContext(config: SparkConf) extends Logging with ExecutorAllocationCli
14811490 logInfo(" SparkContext already stopped." )
14821491 return
14831492 }
1493+ if (_shutdownHookRef != null ) {
1494+ Utils .removeShutdownHook(_shutdownHookRef)
1495+ }
14841496
14851497 postApplicationEnd()
14861498 _ui.foreach(_.stop())
@@ -1891,7 +1903,7 @@ object SparkContext extends Logging {
18911903 *
18921904 * Access to this field is guarded by SPARK_CONTEXT_CONSTRUCTOR_LOCK.
18931905 */
1894- private val activeContext : AtomicReference [SparkContext ] =
1906+ private val activeContext : AtomicReference [SparkContext ] =
18951907 new AtomicReference [SparkContext ](null )
18961908
18971909 /**
@@ -1944,11 +1956,11 @@ object SparkContext extends Logging {
19441956 }
19451957
19461958 /**
1947- * This function may be used to get or instantiate a SparkContext and register it as a
1948- * singleton object. Because we can only have one active SparkContext per JVM,
1949- * this is useful when applications may wish to share a SparkContext.
1959+ * This function may be used to get or instantiate a SparkContext and register it as a
1960+ * singleton object. Because we can only have one active SparkContext per JVM,
1961+ * this is useful when applications may wish to share a SparkContext.
19501962 *
1951- * Note: This function cannot be used to create multiple SparkContext instances
1963+ * Note: This function cannot be used to create multiple SparkContext instances
19521964 * even if multiple contexts are allowed.
19531965 */
19541966 def getOrCreate (config : SparkConf ): SparkContext = {
@@ -1961,17 +1973,17 @@ object SparkContext extends Logging {
19611973 activeContext.get()
19621974 }
19631975 }
1964-
1976+
19651977 /**
1966- * This function may be used to get or instantiate a SparkContext and register it as a
1967- * singleton object. Because we can only have one active SparkContext per JVM,
1978+ * This function may be used to get or instantiate a SparkContext and register it as a
1979+ * singleton object. Because we can only have one active SparkContext per JVM,
19681980 * this is useful when applications may wish to share a SparkContext.
1969- *
1981+ *
19701982 * This method allows not passing a SparkConf (useful if just retrieving).
1971- *
1972- * Note: This function cannot be used to create multiple SparkContext instances
1973- * even if multiple contexts are allowed.
1974- */
1983+ *
1984+ * Note: This function cannot be used to create multiple SparkContext instances
1985+ * even if multiple contexts are allowed.
1986+ */
19751987 def getOrCreate (): SparkContext = {
19761988 getOrCreate(new SparkConf ())
19771989 }
0 commit comments