-
Notifications
You must be signed in to change notification settings - Fork 85
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Getting more information when a StackOverflowError occurs #161
base: main
Are you sure you want to change the base?
Getting more information when a StackOverflowError occurs #161
Conversation
When unmarshalling a very deep object structure, this can raise StackOverflowError. There are multiple issues with the existing implementation, preventing attachment of TraceInformation to such object. * StackOverflowError doesn't support adding a cause (the current mechanism used by TraceInformation) * Adding TraceInformation as suppressed exception can itself lead to a new StackOverflowError.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks sensible. Note that this project has accepted diagnostic patches motivated by Jenkins Pipeline usage in the past: 83738e5
TraceInformation ti; | ||
if (optionalTi.isEmpty()) { | ||
ti = new TraceInformation(); | ||
t.addSuppressed(ti); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems sensible. Did you notice if there was any test coverage for this facility?
@@ -207,6 +207,8 @@ Object doReadNestedObject(final boolean unshared, final String enclosingClassNam | |||
} catch (RuntimeException e) { | |||
TraceInformation.addIncompleteObjectInformation(e, enclosingClassName); | |||
throw e; | |||
} catch (StackOverflowError e) { | |||
throw new RuntimeException(e); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we be calling TraceInformation.addIncompleteObjectInformation
here too? I suppose it would be added by the next stack frame up?
You can, actually, by using
I guess "going up one level" is to avoid a recursive stack overflow? I wonder if it would be a good idea to add a simple object-depth limiter. We already track the depth for the purposes of filtering, so it shouldn't be too hard to add a check to detect a maximum object depth violation and throw a
It's currently JIRA, but with the intention of migrating to GitHub. I think the README probably just got copy-pasted though; sorry about that. Maybe this is the prompting I need to get the migration going. |
Ah, I may have been confused by the recursive
You guess right.
Not sure what would be an appropriate value. In Jenkins case, the object tree being marshalled/unmarshalled is derived from a user input. The problem right now with the SOE is that we are unable to collect |
In my debug session, I think this is because the JVM doesn't use the constructor to create |
Right, and even if one could do so, it would be highly JVM- and platform-specific as to how the stack size in bytes translates to call frames and thus to allowable recursion depth. It's too bad they don't even let you access something like a percentage like This is not really a solution, or even directly related, but it's worth mentioning on this thread that you can independently establish a stack size on a per-thread basis if you construct the |
I think you could find it using a bisect methodology; start with, say, 100. If you hit the limit, it's too low; if you hit SOE, it's too high; if you hit both then your stack is too small. Limiting depth is also useful for preventing DoS attacks when the payload might somehow be derived from an untrusted source. |
Thanks for the tip. It does work in a test environment (jenkinsci/workflow-cps-plugin#993) though it does not look great for production code. |
Yeah, it's a little ugly. :-) |
Hello 👋 ,
I work on the Jenkins project, and I'm investigating issues we're seeing while using this library to marshal and unmarshal a pipeline runtime state.
When marshalling or unmarshalling a very deep object structure, this can raise
StackOverflowError
depending on the configured JVM stack size.Unfortunately, the current implementation only catches various exceptions, not
StackOverflowError
. In addition, when catching these the existing mecanism to attachTraceInformation
doesn't work.StackOverflowError
doesn't support adding a cause (the current mechanism used by TraceInformation)TraceInformation
as suppressed exception can itself lead to a newStackOverflowError
.These experimental changes do 2 things:
TraceInformation
.StackOverflowError
into aRuntimeException
. That way, theTraceInformation
object can be attached as soon as the catching code goes up one level.I don't expect this to be merged at all, it is more of a way to open discussion.
While looking at the project, I was also a bit confused:
So which is it?