Skip to content
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

RingBufferLogHandler.records could leak records #6018

Merged
merged 1 commit into from
Dec 7, 2021

Conversation

jglick
Copy link
Member

@jglick jglick commented Dec 6, 2021

As @PierreBtz points out in jenkinsci/support-core-plugin#324 (review), if someone set up a custom logger that recorded messages from Pipeline components, it could temporarily hold on to GroovyClassLoaders from completed builds, which is not something we want as these might be quite large; seems preferable to let log messages be dropped under extreme memory pressure conditions. Perhaps it is possible to use PhantomReference to replace a record with its formatted equivalent just before collection but this seems like overengineering.

Note that in both the core and plugin cases, it is not exactly correct to hold a list of unformatted LogRecords at all, when they are not going to be immediately written to some log sink. For example code like this

AtomicInteger x = new AtomicInteger();
void doSomething() {
    LOGGER.log(Level.FINE, "running with x={0}", x);
    use(x.incrementAndGet());
}

would send messages like

running with x=0
running with x=1
running with x=2

to a log file, but display

running with x=3
running with x=3
running with x=3

in a GUI display. Unfortunately there is no way to know for sure if the sub-INFO record is going to ever be formatted, so formatting eagerly in publish would usually be wasteful just in order to properly handle log messages from code using this antipattern (log record parameters whose toString depends on mutable state).

I am also cleaning up some concurrency code that looked dubious in f999510 and more so in #5772. Since accesses to start and size are synchronized, why use additional constructs? Perhaps this made sense when returning a lazily evaluated list, though I am not convinced its implementation was ever correct. Simpler and clearer to just construct a concrete list of results if and when getView is called, which is done for example in

<t:logRecords logRecords="${it.logRecords}"/>

Proposed changelog entries

  • Custom log records with large record parameters no longer interfere with garbage collection.

Maintainer checklist

Before the changes are marked as ready-for-merge:

  • There are at least 2 approvals for the pull request and no outstanding requests for change
  • Conversations in the pull request are over OR it is explicit that a reviewer does not block the change
  • Changelog entries in the PR title and/or Proposed changelog entries are correct
  • Proper changelog labels are set so that the changelog can be generated automatically
  • If the change needs additional upgrade steps from users, upgrade-guide-needed label is set and there is a Proposed upgrade guidelines section in the PR title. (example)
  • If it would make sense to backport the change to LTS, a Jira issue must exist, be a Bug or Improvement, and be labeled as lts-candidate to be considered (see query).

assertFalse(lr.handler.getView().contains(r4));
assertTrue(lr.handler.getView().contains(r5));
assertTrue(lr.handler.getView().contains(r6));
assertThat(lr.handler.getView(), contains(r6, r5, r1));
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Strengthening test to assert order as well.

@basil basil requested a review from a team December 6, 2021 18:50
@timja timja added bug For changelog: Minor bug. Will be listed after features ready-for-merge The PR is ready to go, and it will be merged soon if there is no negative feedback labels Dec 6, 2021
@timja
Copy link
Member

timja commented Dec 6, 2021

This PR is now ready for merge, after ~24 hours, we will merge it if there's no negative feedback.

Thanks!

@basil basil merged commit b6cec36 into jenkinsci:master Dec 7, 2021
@jglick jglick deleted the RingBufferLogHandler.records branch December 8, 2021 13:47
@timja
Copy link
Member

timja commented Dec 9, 2021

git bisect identifies this as the revision that has broken ATH (picked up in jenkinsci/acceptance-test-harness#716).

b6cec365302c88143c80ec2c42f82deb99d81865 is the first bad commit
commit b6cec365302c88143c80ec2c42f82deb99d81865
Author: Jesse Glick <[email protected]>
Date:   Tue Dec 7 17:49:38 2021 -0500

    `RingBufferLogHandler.records` could leak records (#6018)

 .../java/hudson/util/RingBufferLogHandler.java     | 49 +++++++++++-----------
 .../test/java/hudson/logging/LogRecorderTest.java  |  9 ++--
 2 files changed, 28 insertions(+), 30 deletions(-)

System log no longer works after this change:

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug For changelog: Minor bug. Will be listed after features ready-for-merge The PR is ready to go, and it will be merged soon if there is no negative feedback
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants