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

examples/addr2line: flush stdout after each response #210

Merged
merged 1 commit into from
Mar 25, 2021

Conversation

anakryiko
Copy link
Contributor

Forcefully flush stdout after each address is handled. This allows to use
addr2line in a "coprocess" mode, in which another process forks/execs
addr2line, establishes two uni-directional pipes for passing input addresses
and reading back responses, and uses addr2line in a client/server fashion.
This is done for amortizing start up costs and make stack symbolization as
cheap as possible.

The problem with the above "coprocess" mode is that because addr2line is
getting Unix pipes for stdin/stdout, std::io::stdin()/std::io::stdout() will
switch to fully buffered mode, instead of line-buffered one that happens when
stdin/stdout is wired to interactive shell. Because of that buffering, driving
application will never get response (unless it's bigger than internal buffer,
which is quite big, though I don't know exactly how big), because it will
never be actually flushed into the pipe. This problem generically is solved
through a complicated dance with setting up pseudo-terminal, creating new
session, etc, etc. It's complicated enough to discourage such use completely.

But if we can modify addr2line to enforce flushing data after each response,
then all this problem goes away, because buffering doesn't matter much
anymore. It shouldn't hurt performance noticeably at all.

Signed-off-by: Andrii Nakryiko andrii@kernel.org

Forcefully flush stdout after each address is handled. This allows to use
addr2line in a "coprocess" mode, in which another process forks/execs
addr2line, establishes two uni-directional pipes for passing input addresses
and reading back responses, and uses addr2line in a client/server fashion.
This is done for amortizing start up costs and make stack symbolization as
cheap as possible.

The problem with the above "coprocess" mode is that because addr2line is
getting Unix pipes for stdin/stdout, std::io::stdin()/std::io::stdout() will
switch to fully buffered mode, instead of line-buffered one that happens when
stdin/stdout is wired to interactive shell. Because of that buffering, driving
application will never get response (unless it's bigger than internal buffer,
which is quite big, though I don't know exactly how big), because it will
never be actually flushed into the pipe. This problem generically is solved
through a complicated dance with setting up pseudo-terminal, creating new
session, etc, etc. It's complicated enough to discourage such use completely.

But if we can modify addr2line to enforce flushing data after each response,
then all this problem goes away, because buffering doesn't matter much
anymore. It shouldn't hurt performance noticeably at all.

Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Copy link
Contributor

@philipc philipc left a comment

Choose a reason for hiding this comment

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

Thanks!

Note that currently this code is intentionally placed in examples/ rather than src/bin/, and it is not a mature replacement for the addr2line from binutils or llvm.

@philipc philipc merged commit a8d5d50 into gimli-rs:master Mar 25, 2021
@anakryiko anakryiko deleted the flush-stdout branch March 25, 2021 04:35
@anakryiko
Copy link
Contributor Author

Note that currently this code is intentionally placed in examples/ rather than src/bin/, and it is not a mature replacement for the addr2line from binutils or llvm.

Yeah, I realize that. But it seems to be working very well for kernel stack trace symbolization. I'm using it in my proof-of-concept tool at https://github.com/anakryiko/retsnoop, and it's surprisingly fast and reliable. So thanks a lot for adding that examples/addr2line part!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants