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

Improve presentation of remote exception

    XMLWordPrintable

    Details

    • Type: Bug
    • Status: Resolved (View Workflow)
    • Priority: Minor
    • Resolution: Fixed
    • Component/s: remoting
    • Labels:
      None
    • Similar Issues:

      Description

      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.

      Jesse Glick,Stephen Connolly,Oleg Nenashev, thoughts?

        Attachments

          Activity

          Hide
          oleg_nenashev Oleg Nenashev added a comment -

          I definitely vote for #1 and #2.

          #3 seems to be more complicated to me, maybe we would rather like to introduce a "RemoteException" wrapper. Actually it's already kinda exists for serializing non-serializable exceptions, but we could improve it and add our own exception rendering.

          Show
          oleg_nenashev Oleg Nenashev added a comment - I definitely vote for #1 and #2. #3 seems to be more complicated to me, maybe we would rather like to introduce a "RemoteException" wrapper. Actually it's already kinda exists for serializing non-serializable exceptions, but we could improve it and add our own exception rendering.
          Hide
          olivergondza Oliver Gondža added a comment -

          I do not think there is a way to implement wrapper as the call is supposed to throw exception of type parameter of Callable.

          Show
          olivergondza Oliver Gondža added a comment - I do not think there is a way to implement wrapper as the call is supposed to throw exception of type parameter of Callable .
          Hide
          olivergondza Oliver Gondža added a comment -

          No further opinions so I stick with the simplest improvement.

          Show
          olivergondza Oliver Gondža added a comment - No further opinions so I stick with the simplest improvement.
          Hide
          jglick Jesse Glick added a comment -

          #1 seems fine.

          Note that current versions of Jenkins core will display causes and suppressed throwables a little differently from the Java default. Best to show that. (cf. Functions.printThrowable)

          Show
          jglick Jesse Glick added a comment - #1 seems fine. Note that current versions of Jenkins core will display causes and suppressed throwables a little differently from the Java default. Best to show that. (cf. Functions.printThrowable )
          Hide
          scm_issue_link SCM/JIRA link daemon added a comment -

          Code changed in jenkins
          User: Oliver Gondža
          Path:
          src/main/java/hudson/remoting/Channel.java
          src/test/java/hudson/remoting/ChannelTest.java
          http://jenkins-ci.org/commit/remoting/ef7e916883f1818023a11776ff4d2057eaf39fd5
          Log:
          [FIXED JENKINS-46140] Improve presentation of remote exception

          Show
          scm_issue_link SCM/JIRA link daemon added a comment - Code changed in jenkins User: Oliver Gondža Path: src/main/java/hudson/remoting/Channel.java src/test/java/hudson/remoting/ChannelTest.java http://jenkins-ci.org/commit/remoting/ef7e916883f1818023a11776ff4d2057eaf39fd5 Log: [FIXED JENKINS-46140] Improve presentation of remote exception
          Hide
          scm_issue_link SCM/JIRA link daemon added a comment -

          Code changed in jenkins
          User: Oleg Nenashev
          Path:
          src/main/java/hudson/remoting/Channel.java
          src/test/java/hudson/remoting/ChannelTest.java
          http://jenkins-ci.org/commit/remoting/4f8e9da5c75b48013428df2bbbb6517d80122304
          Log:
          Merge pull request #189 from olivergondza/JENKINS-46140

          [FIXED JENKINS-46140] Improve presentation of remote exception

          Compare: https://github.com/jenkinsci/remoting/compare/c9d858a50cea...4f8e9da5c75b

          Show
          scm_issue_link SCM/JIRA link daemon added a comment - Code changed in jenkins User: Oleg Nenashev Path: src/main/java/hudson/remoting/Channel.java src/test/java/hudson/remoting/ChannelTest.java http://jenkins-ci.org/commit/remoting/4f8e9da5c75b48013428df2bbbb6517d80122304 Log: Merge pull request #189 from olivergondza/ JENKINS-46140 [FIXED JENKINS-46140] Improve presentation of remote exception Compare: https://github.com/jenkinsci/remoting/compare/c9d858a50cea...4f8e9da5c75b
          Hide
          scm_issue_link SCM/JIRA link daemon added a comment -

          Code changed in jenkins
          User: Oleg Nenashev
          Path:
          pom.xml
          http://jenkins-ci.org/commit/jenkins/018f9875ca58230afc4eb52ac66b3195f00128ef
          Log:
          [JENKINS-45755, JENKINS-46140] - Update Remoting to 3.12

          https://github.com/jenkinsci/remoting/blob/master/CHANGELOG.md#312

          Show
          scm_issue_link SCM/JIRA link daemon added a comment - Code changed in jenkins User: Oleg Nenashev Path: pom.xml http://jenkins-ci.org/commit/jenkins/018f9875ca58230afc4eb52ac66b3195f00128ef Log: [JENKINS-45755, JENKINS-46140] - Update Remoting to 3.12 https://github.com/jenkinsci/remoting/blob/master/CHANGELOG.md#312
          Hide
          scm_issue_link SCM/JIRA link daemon added a comment -

          Code changed in jenkins
          User: Oleg Nenashev
          Path:
          pom.xml
          http://jenkins-ci.org/commit/jenkins/e8b2f5a59c0b075f62bea9b6a45ef35a1c2ca1bb
          Log:
          Merge pull request #3025 from oleg-nenashev/remoting/3.12

          [JENKINS-45755, JENKINS-46140] - Update Remoting to 3.12

          Compare: https://github.com/jenkinsci/jenkins/compare/2343909f0240...e8b2f5a59c0b

          Show
          scm_issue_link SCM/JIRA link daemon added a comment - Code changed in jenkins User: Oleg Nenashev Path: pom.xml http://jenkins-ci.org/commit/jenkins/e8b2f5a59c0b075f62bea9b6a45ef35a1c2ca1bb Log: Merge pull request #3025 from oleg-nenashev/remoting/3.12 [JENKINS-45755, JENKINS-46140] - Update Remoting to 3.12 Compare: https://github.com/jenkinsci/jenkins/compare/2343909f0240...e8b2f5a59c0b

            People

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

              Dates

              • Created:
                Updated:
                Resolved: