Skip to content

Commit a33b9fc

Browse files
summaryzbLuciferYang
authored andcommitted
[SPARK-51691][CORE][TESTS] SerializationDebugger should swallow exception when try to find the reason of serialization problem
### What changes were proposed in this pull request? Catch `SparkRuntimeException` when deep into serialization exception stack during unit test. ### Why are the changes needed? Present a clearer serialization exception stack hierarchy during test, `toString` implementation of `TreeNode` may throw exception since `SQLConf.get` check. It is helpful for debug the real problem ### Does this PR introduce _any_ user-facing change? Yes, but it only take effect in unit test. User will see the direct serialization exception and the reference chain beyond the root cause. Before this pr, user will get confuse when unrelated exception is shown ``` WARN org.apache.spark.serializer.SerializationDebugger: Exception in serialization debugger org.apache.spark.SparkRuntimeException: Cannot get SQLConf inside scheduler event loop thread. at org.apache.spark.sql.errors.QueryExecutionErrors$.cannotGetSQLConfInSchedulerEventLoopThreadError(QueryExecutionErrors.scala:2002) at org.apache.spark.sql.internal.SQLConf$.get(SQLConf.scala:225) at org.apache.spark.sql.execution.ScalarSubquery.toString(subquery.scala:69) at java.lang.String.valueOf(String.java:2994) at scala.collection.mutable.StringBuilder.append(StringBuilder.scala:203) at scala.collection.immutable.Stream.addString(Stream.scala:701) at scala.collection.TraversableOnce.mkString(TraversableOnce.scala:377) org.apache.spark.SparkException: Job aborted due to stage failure: Task not serializable: java.io.NotSerializableException: org.apache.spark.SimpleFutureAction ``` After this pr ``` org.apache.spark.SparkException: Job aborted due to stage failure: Task not serializable: java.io.NotSerializableException: org.apache.spark.SimpleFutureAction Serialization stack: - object not serializable (class: org.apache.spark.SimpleFutureAction, value: org.apache.spark.SimpleFutureAction4050649d) - writeObject data (class: java.util.concurrent.ConcurrentHashMap) - object (class java.util.concurrent.ConcurrentHashMap) ....(not shown) ``` ### How was this patch tested? Pass GitHub Actions ### Was this patch authored or co-authored using generative AI tooling? No Closes #50489 from summaryzb/SPARK-51691. Authored-by: summaryzb <summaryzb@gmail.com> Signed-off-by: yangjie01 <yangjie01@baidu.com>
1 parent a0bc044 commit a33b9fc

File tree

2 files changed

+28
-3
lines changed

2 files changed

+28
-3
lines changed

core/src/main/scala/org/apache/spark/serializer/SerializationDebugger.scala

+9-2
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,10 @@ import scala.annotation.tailrec
2626
import scala.collection.mutable
2727
import scala.util.control.NonFatal
2828

29+
import org.apache.spark.SparkRuntimeException
2930
import org.apache.spark.internal.Logging
3031
import org.apache.spark.util.SparkClassUtils
32+
import org.apache.spark.util.Utils
3133

3234
private[spark] object SerializationDebugger extends Logging {
3335

@@ -110,8 +112,13 @@ private[spark] object SerializationDebugger extends Logging {
110112
val elem = s"externalizable object (class ${e.getClass.getName}, $e)"
111113
visitExternalizable(e, elem :: stack)
112114

113-
case s: Object with java.io.Serializable =>
114-
val elem = s"object (class ${s.getClass.getName}, $s)"
115+
case s: Object with java.io.Serializable if Utils.isTesting =>
116+
val str = try {
117+
s.toString
118+
} catch {
119+
case _: SparkRuntimeException => "exception in toString"
120+
}
121+
val elem = s"object (class ${s.getClass.getName}, $str)"
115122
visitSerializable(s, elem :: stack)
116123

117124
case _ =>

core/src/test/scala/org/apache/spark/serializer/SerializationDebuggerSuite.scala

+19-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import java.io._
2121

2222
import scala.annotation.meta.param
2323

24-
import org.apache.spark.SparkFunSuite
24+
import org.apache.spark.{SparkFunSuite, SparkRuntimeException}
2525

2626
class SerializationDebuggerSuite extends SparkFunSuite {
2727

@@ -180,6 +180,15 @@ class SerializationDebuggerSuite extends SparkFunSuite {
180180
assert(e.getMessage.contains("SerializableClass2")) // found debug trace should be present
181181
}
182182

183+
test("SPARK-51691 improveException swallow underlying exception") {
184+
val e = SerializationDebugger.improveException(
185+
new SerializableClassWithStringException(new NotSerializable),
186+
new NotSerializableException("someClass"))
187+
assert(e.getMessage.contains("exception in toString"))
188+
assert(e.getMessage.contains("someClass"))
189+
assert(e.getMessage.contains("SerializableClassWithStringException"))
190+
}
191+
183192
test("improveException with error in debugger") {
184193
// Object that throws exception in the SerializationDebugger
185194
val o = new SerializableClass1 {
@@ -205,6 +214,15 @@ class SerializableClass1 extends Serializable
205214

206215
class SerializableClass2(val objectField: Object) extends Serializable
207216

217+
class SerializableClassWithStringException(val objectField: Object) extends Serializable {
218+
override def toString: String = {
219+
// simulate the behavior of TreeNode#toString that SQLConf.get may throw exception
220+
throw new SparkRuntimeException(errorClass = "INTERNAL_ERROR",
221+
messageParameters = Map("message" -> "this is an internal error"),
222+
cause = null)
223+
}
224+
}
225+
208226

209227
class SerializableArray(val arrayField: Array[Object]) extends Serializable
210228

0 commit comments

Comments
 (0)