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

Use bufio.Reader instead of bufio.Scanner for logger.Copier #13564

Merged
merged 1 commit into from
May 29, 2015

Conversation

burke
Copy link
Contributor

@burke burke commented May 28, 2015

When using a scanner, log lines over 64K will crash the Copier with bufio.ErrTooLong. Subsequently, the ioutils.bufReader will grow without bound as the logs are no longer being flushed to disk.

For us, this manifested as some background workers occasionally stopping log writes, and slow memory growth between deploys.

@jessfraz
Copy link
Contributor

you are awesome :)

reader := bufio.NewReader(src)

for {
line, err := reader.ReadString('\n')
Copy link
Contributor

Choose a reason for hiding this comment

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

How about ReadBytes?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh yeah, good point, I forgot that one existed. Will update.

@burke burke force-pushed the fix-memory-leak branch 3 times, most recently from 1ace45e to 4c515fe Compare May 28, 2015 22:15
return
}
logrus.Errorf("Error scanning log stream: %s", err)
return
Copy link
Contributor

Choose a reason for hiding this comment

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

I think you can remove the double return by doing something like:

if err != io.EOF {
    logrus.Errorf("Error scanning log stream: %s", err)
}
return

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I have this sense that comparing nil with io.EOF at runtime causes a panic but I can't remember why... I'll give it a shot.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh, yeah, nevermind, I see what you're saying.

Copy link
Contributor

Choose a reason for hiding this comment

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

but you compared that err != nil in the line before.

@burke burke force-pushed the fix-memory-leak branch from 4c515fe to c0b4fcb Compare May 28, 2015 22:34
@calavera
Copy link
Contributor

LGTM

@calavera calavera added this to the 1.7.0 milestone May 28, 2015
@calavera
Copy link
Contributor

I think this can go into 1.7, but feel free to remove it from the milestone.

@calavera calavera added the kind/bug Bugs are bugs. The cause may or may not be known at triage time so debugging may be needed. label May 28, 2015
@cpuguy83
Copy link
Member

ping @unclejack

@cpuguy83
Copy link
Member

This closes #13333

@burke burke force-pushed the fix-memory-leak branch from c0b4fcb to e8b9a61 Compare May 29, 2015 01:20
reader := bufio.NewReader(src)

for {
lineAndNewline, err := reader.ReadBytes('\n')
Copy link
Contributor

Choose a reason for hiding this comment

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

I kinda liked your lightweight solution with slicing. I think might be:

line, err := reader.ReadBytes('\n')
line = line[:len(line)-1]

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So the problem I had, and the reason I changed the commit, is that ReadBytes can return an error and a partial output. I haven't tested this, but I'm assuming that if it returns a partial input, it will end with a valuable byte and not a newline -- so it's probably prudent to only trim the trailing character if it's a newline.

Copy link
Contributor

Choose a reason for hiding this comment

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

Okay, anyway then you should reuse one variable :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Works for me. Changed.

When using a scanner, log lines over 64K will crash the Copier with
bufio.ErrTooLong. Subsequently, the ioutils.bufReader will grow without
bound as the logs are no longer being flushed to disk.

Signed-off-by: Burke Libbey <burke.libbey@shopify.com>
@burke burke force-pushed the fix-memory-leak branch from e8b9a61 to f779cfc Compare May 29, 2015 16:29
@LK4D4
Copy link
Contributor

LK4D4 commented May 29, 2015

LGTM

LK4D4 added a commit that referenced this pull request May 29, 2015
Use bufio.Reader instead of bufio.Scanner for logger.Copier
@LK4D4 LK4D4 merged commit c42810f into moby:master May 29, 2015
@burke burke mentioned this pull request Jun 1, 2015
@jessfraz
Copy link
Contributor

cherry-picked

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind/bug Bugs are bugs. The cause may or may not be known at triage time so debugging may be needed. status/2-code-review
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants