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

Handle execve's on Linux #177

Merged
merged 4 commits into from May 20, 2019

Conversation

Projects
None yet
2 participants
@wabain
Copy link
Contributor

commented Sep 4, 2018

This is a fix for #145, handling exec calls, for Linux. While the same approach should work for MacOS, extra work would be needed to distinguish between invalid reads and process exit and since I've already let this sit for many months, I'd prefer to land Linux support.

The idea here is to check the result returned when getting the stack trace from the target process to detect the error that the pointer to the ruby thread state, specifically, has become invalid. If it has, we then reinitialize StackTraceGetter on the basis that if we've lost the thread the whole process is invalid.

In the test case I added I'm polling until the reinitialization happens. I did this because when I used a fixed timeout I was sometimes getting the trace before reinitialization (one every 500 test runs or so), and I didn't want to play the timeout tweaking game. With the current polling I still get the error "stack base and cfp address out of sync" once every few thousand test runs but I think that error should be transient and shouldn't impact real usage.

wabain added some commits Aug 24, 2018

Handle execve's on Linux
When an execve is executed, the process's memory is replaced with the memory
of a new program. When the new program is also a Ruby interpreter instance,
rbspy should continue to gather stack traces. This is particularly important
because some Ruby invocation methods, such as rvm, may do an execve to launch
the script being invoked by the user.

The strategy here is to check the result returned when getting the stack trace
from the target process to detect the error that the pointer into the ruby
thread state, specifically, has become invalid. If it has, we then reinitialize
StackTraceGetter on the basis that if we've lost our thread the whole process
is invalid.

Currently this doesn't work on MacOS because the error-handling for copying
addresses can't distinguish between an invalid read and process exit.
Fixing that would require either changing the interface of
read-process-memory to surface the mach return codes or just working around
it in rbspy.

It might also not work as reliably on 32-bit platforms, where there may be
a greater chance of the thread state pointer being remapped into the
memory of the new process.
Clean up stack trace type declarations
Make StackTraceGetter take ProcessHandle instead of a generic,
since doing anything meaningful with StackTraceGetter now requires
it to support reinitialization. Add a type alias for the boxed
stack trace type.

@wabain wabain force-pushed the wabain:execve-support branch from 4a46622 to 3c83f39 Feb 9, 2019

@wabain wabain changed the title WIP: Handle execve's Handle execve's on Linux Feb 9, 2019

@neosilky

This comment has been minimized.

Copy link
Collaborator

commented May 20, 2019

Looks good to me and appears to fix #145 👍

@neosilky neosilky merged commit 806ace5 into rbspy:master May 20, 2019

2 checks passed

continuous-integration/appveyor/pr AppVeyor build succeeded
Details
continuous-integration/travis-ci/pr The Travis CI build passed
Details

@neosilky neosilky referenced this pull request May 21, 2019

Open

os error 14 on Ubuntu #145

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.