Uploaded image for project: 'Jenkins'
  1. Jenkins
  2. JENKINS-46140

Improve presentation of remote exception

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Fixed
    • Icon: Minor Minor
    • remoting
    • None

      For a long time, remoting has a way to decorate received exception will a "call side" stacktrace but that is just pain to navigate even with decent application knowledge (one tells local and remote stack frames apart based on the classes involved rather then the way exception is presented). Putting aside fiddling with stacktraces the way Channel.attachCallSiteStackTrace does is dangerous at best. In Java 9 code will need to be further complicated or module information will be thrown away. Here is how it looks like now:

      java.io.IOException: Local nested
        at hudson.remoting.ChannelTest.testCallSiteStacktrace(ChannelTest.java:191)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at junit.framework.TestCase.runTest(TestCase.java:176)
        at junit.framework.TestCase.runBare(TestCase.java:141)
        at junit.framework.TestResult$1.protect(TestResult.java:122)
        at junit.framework.TestResult.runProtected(TestResult.java:142)
        at junit.framework.TestResult.run(TestResult.java:125)
        at junit.framework.TestCase.run(TestCase.java:129)
        at junit.framework.TestSuite.runTest(TestSuite.java:252)
        at junit.framework.TestSuite.run(TestSuite.java:247)
        at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:86)
        at org.apache.maven.surefire.junit4.JUnit4Provider.executeFailedMethod(JUnit4Provider.java:381)
        at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:292)
        at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:238)
        at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:161)
        at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:290)
        at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:242)
        at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:121)
      Caused by: java.io.IOException: Node nested
        at hudson.remoting.ChannelTest$ThrowingCallable.call(ChannelTest.java:197)
        at hudson.remoting.ChannelTest$ThrowingCallable.call(ChannelTest.java:195)
        at hudson.remoting.UserRequest.perform(UserRequest.java:203)
        at hudson.remoting.UserRequest.perform(UserRequest.java:52)
        at hudson.remoting.Request$2.run(Request.java:356)
        at hudson.remoting.InterceptingExecutorService$1.call(InterceptingExecutorService.java:68)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at java.lang.Thread.run(Thread.java:748)
        at ......remote call to north(Native Method)
        at hudson.remoting.Channel.attachCallSiteStackTrace(Channel.java:1647)
        at hudson.remoting.UserResponse.retrieve(UserRequest.java:303)
        at hudson.remoting.Channel.call(Channel.java:896)
        at hudson.remoting.ChannelTest.testCallSiteStacktrace(ChannelTest.java:189)
        ... 20 more
      Caused by: java.io.IOException: Node says hello!
        at hudson.remoting.ChannelTest$ThrowingCallable.call(ChannelTest.java:197)
        at hudson.remoting.ChannelTest$ThrowingCallable.call(ChannelTest.java:195)
        at hudson.remoting.UserRequest.perform(UserRequest.java:203)
        at hudson.remoting.UserRequest.perform(UserRequest.java:52)
        at hudson.remoting.Request$2.run(Request.java:356)
        at hudson.remoting.InterceptingExecutorService$1.call(InterceptingExecutorService.java:68)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
        at java.lang.Thread.run(Thread.java:748)
      

      Proposal #1: Suppressed exception.

      Well, it is not a suppressed exception but it is trivial to implement and there is so little to go wrong about it. Stacktraces are untouched and the top-level exception coming from the other side has the call-site attached. The call side stacktrace is complete and clearly separated but it still requires some training to identify what is going on.

      java.io.IOException: Local nested
      	at hudson.remoting.ChannelTest.testCallSiteStacktrace(ChannelTest.java:191)
      	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
      	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      	at java.lang.reflect.Method.invoke(Method.java:498)
      	at junit.framework.TestCase.runTest(TestCase.java:176)
      	at junit.framework.TestCase.runBare(TestCase.java:141)
      	at junit.framework.TestResult$1.protect(TestResult.java:122)
      	at junit.framework.TestResult.runProtected(TestResult.java:142)
      	at junit.framework.TestResult.run(TestResult.java:125)
      	at junit.framework.TestCase.run(TestCase.java:129)
      	at junit.framework.TestSuite.runTest(TestSuite.java:252)
      	at junit.framework.TestSuite.run(TestSuite.java:247)
      	at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:86)
      	at org.apache.maven.surefire.junit4.JUnit4Provider.executeFailedMethod(JUnit4Provider.java:381)
      	at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:292)
      	at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:238)
      	at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:161)
      	at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:290)
      	at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:242)
      	at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:121)
      Caused by: java.io.IOException: Node nested
      	at hudson.remoting.ChannelTest$ThrowingCallable.call(ChannelTest.java:197)
      	at hudson.remoting.ChannelTest$ThrowingCallable.call(ChannelTest.java:195)
      	at hudson.remoting.UserRequest.perform(UserRequest.java:203)
      	at hudson.remoting.UserRequest.perform(UserRequest.java:52)
      	at hudson.remoting.Request$2.run(Request.java:356)
      	at hudson.remoting.InterceptingExecutorService$1.call(InterceptingExecutorService.java:68)
      	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
      	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
      	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
      	at java.lang.Thread.run(Thread.java:748)
      	Suppressed: hudson.remoting.Channel$CallSiteStackTrace: Remote call to north
      		at hudson.remoting.Channel.attachCallSiteStackTrace(Channel.java:1647)
      		at hudson.remoting.UserResponse.retrieve(UserRequest.java:303)
      		at hudson.remoting.Channel.call(Channel.java:896)
      		at hudson.remoting.ChannelTest.testCallSiteStacktrace(ChannelTest.java:189)
      		at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      		at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
      		at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      		at java.lang.reflect.Method.invoke(Method.java:498)
      		at junit.framework.TestCase.runTest(TestCase.java:176)
      		at junit.framework.TestCase.runBare(TestCase.java:141)
      		at junit.framework.TestResult$1.protect(TestResult.java:122)
      		at junit.framework.TestResult.runProtected(TestResult.java:142)
      		at junit.framework.TestResult.run(TestResult.java:125)
      		at junit.framework.TestCase.run(TestCase.java:129)
      		at junit.framework.TestSuite.runTest(TestSuite.java:252)
      		at junit.framework.TestSuite.run(TestSuite.java:247)
      		at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:86)
      		at org.apache.maven.surefire.junit4.JUnit4Provider.executeFailedMethod(JUnit4Provider.java:381)
      		at org.apache.maven.surefire.junit4.JUnit4Provider.executeWithRerun(JUnit4Provider.java:292)
      		at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:238)
      		at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:161)
      		at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:290)
      		at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:242)
      		at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:121)
      Caused by: java.io.IOException: Node says hello!
      	... 10 more
      

      Proposal #2: Prefix stackframes with channel destination name if remote.

      This can be combined with existing approach and #1 to signify which exception (trace element) is coming from each side but it does require tempering with {{StackTraceElement}}s.

      Proposal #3: Update remote exception message with text indicating those are remote.

       

      Can be combined approach and #1. Requires reflection to work correctly. Might not have effect for certain exception types.

       

      Note sure what other ways there are but my preferred approach is #1.

      jglick,stephenconnolly,oleg_nenashev, thoughts?

            olivergondza Oliver Gondža
            olivergondza Oliver Gondža
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated:
              Resolved: