logback-android icon indicating copy to clipboard operation
logback-android copied to clipboard

NPE in ThrowableProxy

Open bakua opened this issue 5 years ago • 8 comments

Description

I get reported below exception from some users when calling org.slf4j.Logger#error(java.lang.String, java.lang.Throwable)

Fatal Exception: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Object java.lang.StackTraceElement[].clone()' on a null object reference
       at ch.qos.logback.classic.spi.ThrowableProxy.()
       at ch.qos.logback.classic.spi.ThrowableProxy.()
       at ch.qos.logback.classic.spi.LoggingEvent.()
       at ch.qos.logback.classic.Logger.addAppender(Logger.java)
       at ch.qos.logback.classic.Logger.appendLoopOnAppenders(Logger.java)
       at ch.qos.logback.classic.Logger.addAppender(Logger.java)

Steps to reproduce

I don't know how to reproduce.

Environment

  • logback-android version: 2.0.0
  • Android version: So far 5.1 - 6.0.1
  • Platform: any

bakua avatar Jul 26 '19 07:07 bakua

I examined the code indicated in the stack trace, but nothing obvious stood out to me.

To help troubleshoot, can you provide the following?

  • the app source that shows the setup of logback-android and the logger that initiated the exception
  • the app itself (Google Play link or the apk)

tony19 avatar Aug 24 '19 19:08 tony19

Hello, so I got back to this error and found, another library having the same issue: https://github.com/akaita/RxJava2Debug/issues/2

It is caused because of bug on Android 6.0.1 and lower. NPE happens when getting the stack trace:

https://android.googlesource.com/platform/libcore.git/+/android-4.2.2_r1/luni/src/main/java/java/lang/Throwable.java#201 https://android.googlesource.com/platform/libcore.git/+/android-6.0.1_r81/luni/src/main/java/java/lang/Throwable.java#264

The nativeStackTrace() native method returns null, causing the crash at ch/qos/logback/classic/spi/ThrowableProxy.java:64

this.stackTraceElementProxyArray = ThrowableProxyUtil.steArrayToStepArray(throwable
        .getStackTrace());

bakua avatar Oct 03 '19 11:10 bakua

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for reporting the issue.

stale[bot] avatar Dec 02 '19 12:12 stale[bot]

Looking into issue. The solution from RxJava2Debug doesn't seem to apply in our case, since our Throwable is passed in. I think we'll just have totry-catch the call, or skip the call for Android versions <= 6.0.1.

tony19 avatar Feb 29 '20 02:02 tony19

I'm not able to reproduce the bug in the emulator, so I can't test the fix. Do you have a way to reproduce this?

tony19 avatar Feb 29 '20 05:02 tony19

I have actually never been able to reproduce the bug. But now I am using the following to get the stack trace and I don't get crashes anymore.

    public static StackTraceElement[] getSafeStackTrace(Throwable throwable) {
        try {
            return throwable.getStackTrace();
        } catch (NullPointerException ex) {
            return new StackTraceElement[0];
        }
    }

bakua avatar Mar 01 '20 12:03 bakua

Hello! In our project, we use your library. That's a nice tool, thank you very much! We've got this problem described above. It can be easily reproduced. Try to log an instance of such exception:

class ExceptionWithoutStackTrace(message: String) : Exception(message) {
 override fun fillInStackTrace(): Throwable {
    return this
 }
}

So we need to catch an exception when getting a stack trace in ThrowableProxy constructor

devUndef1ned avatar May 11 '20 15:05 devUndef1ned

Also, there is a workaround with current versions of the library. In logback there is such entity like TurboFilter. It's a filter that used to define should we log this before the creation of ILoggingEvent (where the exception has occurred). So we can create a required version of TurboFilter and add it to logback through XML configuration file.

class StackTraceFillFilter : TurboFilter() {
  override fun decide(
    marker: Marker?,
    logger: Logger?,
    level: Level?,
    format: String?,
    params: Array<out Any>?,
    t: Throwable?
  ): FilterReply {
    fixStackTraceFor(t)
    return FilterReply.NEUTRAL
  }

  private fun fixStackTraceFor(t: Throwable?) {
    if (t != null) {
      try {
        t.stackTrace
      } catch (e: Exception) {
        t.stackTrace = arrayOf()
      }
    }
  }

devUndef1ned avatar May 14 '20 13:05 devUndef1ned

Since this issue cannot be reproduced, I'm going to close this for now. Please create a new issue if the problem resurfaces.

tony19 avatar Nov 06 '22 04:11 tony19