private void appendTaskStackTrace ( final Throwable error ) { StackTraceElement [ ] taskStackTrace = _taskStackTraceHolder != null ? _taskStackTraceHolder . getStackTrace ( ) : null ; // At a minimum, any stack trace should have at least 3 stack frames (caller + BaseTask + getStackTrace). // So if there are less than 3 stack frames available then there's something fishy and it's better to ignore them. if ( ! ParSeqGlobalConfiguration . isCrossThreadStackTracesEnabled ( ) || error == null || taskStackTrace == null || taskStackTrace . length <= 2 ) { return ; } StackTraceElement [ ] errorStackTrace = error . getStackTrace ( ) ; if ( errorStackTrace . length <= 2 ) { return ; } // Skip stack frames up to the BaseTask (useless java.util.concurrent stuff) int skipErrorFrames = 1 ; while ( skipErrorFrames < errorStackTrace . length ) { int index = errorStackTrace . length - 1 - skipErrorFrames ; if ( ! errorStackTrace [ index ] . getClassName ( ) . equals ( CANONICAL_NAME ) && errorStackTrace [ index + 1 ] . getClassName ( ) . equals ( CANONICAL_NAME ) ) { break ; } skipErrorFrames ++ ; } // Safeguard against accidentally removing entire stack trace if ( skipErrorFrames == errorStackTrace . length ) { skipErrorFrames = 0 ; } // Skip stack frames up to the BaseTask (useless Thread.getStackTrace stuff) int skipTaskFrames = 1 ; while ( skipTaskFrames < taskStackTrace . length ) { if ( ! taskStackTrace [ skipTaskFrames ] . getClassName ( ) . equals ( CANONICAL_NAME ) && taskStackTrace [ skipTaskFrames - 1 ] . getClassName ( ) . equals ( CANONICAL_NAME ) ) { break ; } skipTaskFrames ++ ; } // Safeguard against accidentally removing entire stack trace if ( skipTaskFrames == taskStackTrace . length ) { skipTaskFrames = 0 ; } int combinedLength = errorStackTrace . length - skipErrorFrames + taskStackTrace . length - skipTaskFrames ; if ( combinedLength <= 0 ) { return ; } StackTraceElement [ ] concatenatedStackTrace = new StackTraceElement [ combinedLength + 1 ] ; System . arraycopy ( errorStackTrace , 0 , concatenatedStackTrace , 0 , errorStackTrace . length - skipErrorFrames ) ; concatenatedStackTrace [ errorStackTrace . length - skipErrorFrames ] = new StackTraceElement ( "********** Task \"" + getName ( ) + "\" (above) was instantiated as following (below): **********" , "" , null , 0 ) ; System . arraycopy ( taskStackTrace , skipTaskFrames , concatenatedStackTrace , errorStackTrace . length - skipErrorFrames + 1 , taskStackTrace . length - skipTaskFrames ) ; error . setStackTrace ( concatenatedStackTrace ) ; }
Concatenate stack traces if kept the original stack trace from the task creation