-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
createdump can read memory with process_vm_readv on Linux #420
Conversation
This system call was added in Linux 3.2, which requires at least RHEL 7. |
We should drop support for RHEL6 for .NET 5. Opened #423 |
Will probably also fix dotnet/diagnostics#548 |
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.
While I like the changes, there are some comments regarding portability and (possible) performance enhancements.
ssize_t read = pread64(m_fd, buffer, size, (off64_t)(ULONG_PTR)address); | ||
iovec local{ buffer, size }; | ||
iovec remote{ (void*)(ULONG_PTR)address, size }; | ||
ssize_t read = process_vm_readv(m_pid, &local, 1, &remote, 1, 0); |
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.
ssize_t
is a signed, 64-bit integer; ULONG32
is an unsigned, 32-bit integer. It's unlikely that read
will be larger than size
as that's the quantity passed as a parameter, however assigning read
to *done
will at least generate a warning.
(Using 32-bit integers to denote sizes is something we should fix throughout the runtime. It should use size_t
throughout.)
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.
Also, are there any places where it would be beneficial to pass an iovec
array rather than just 1 element at a time to process_vm_readv()
? (There could be a fallback method to go through each one and read the memory on OSes that do not offer this particular syscall or a similar feature.)
It might be a good idea to #ifdef
this for Linux only, or check if the syscall exist during build-time. For instance, the FreeBSD procfs
supports /proc/<PID>/mem
but does not have this syscall, so this breaks createdump
on FreeBSD. On systems without process_vm_readv()
but with a compatible procfs
, you might benefit from using readv()
instead of pread()
and have similar speedups if the suggestion above is possible.
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.
There may even be Linux distros that don't support process_vm_readv so a build-time check (like all the other HAVE_xxxx defines) should be added falling back to the proc//mem code.
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.
Distro | Version | Kernel |
---|---|---|
RHEL | 7.0 | 3.10 |
CentOS | 7.0 | 3.10 |
Oracle Linux | 7.0 | 3.10 |
Fedora | 29 | 4.18 |
Debian | 9 | 4.9 |
Ubuntu | 16.04 | 4.4 |
Linux Mint | 18 | 4.4 |
openSUSE | 15 | 4.12 |
SLES | 12 SP2 | 4.4 |
Alpline Linux | 3.8 | 4.14 |
There may even be Linux distros that don't support process_vm_readv
All supported Linux distros meet the minimum version requirement, so I assume it only needs to check for Linux.
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.
For instance, the FreeBSD
procfs
supports/proc/<PID>/mem
The createdump
doc says /proc
doesn't work on FreeBSD. Can you confirm it? Thanks!
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.
Also, are there any places where it would be beneficial to pass an iovec array rather than just 1 element at a time to process_vm_readv()?
There are some parallel read operations, but they are invoked on ICLRDataTarget
instead of DumpDataTarget
. It's not easy to extend that interface.
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.
I wrote that createdump doc 2 or 3 years ago and at the time, it didn't look like FreeBSD supported /proc//mem but now I'm not sure.
@@ -45,6 +45,10 @@ typedef int T_CONTEXT; | |||
#include <sys/user.h> | |||
#include <sys/wait.h> | |||
#include <sys/procfs.h> | |||
#ifdef __linux__ | |||
#include <sys/uio.h> | |||
#define HAVE_READV |
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.
Even though we are sure of such a feature in most modern kernels, why not test for it in
check_function_exists(sigreturn HAVE_SIGRETURN) |
That way we have this consistent, users can build for other platforms with no hard-coded elements, and makes bring-up platforms easier.
The changes look fine to me, thanks for the change :) Right now doing thorough testing is a little harder with the migration - we are not producing official drops we can consume in the broader test infrastructure. Once I get around to that I'll test this and let you know how it goes. |
/azp run |
You have several pipelines (over 10) configured to build pull requests in this repository. Specify which pipelines you would like to run by using /azp run [pipelines] command. You can specify multiple pipelines using a comma separated list. |
/azp list |
/azp run runtime |
Hello @hoyosjs! Because this pull request has the p.s. you can customize the way I help with merging this pull request, such as holding this pull request until a specific person approves. Simply @mention me (
|
Azure Pipelines successfully started running 1 pipeline(s). |
iovec local{ buffer, size }; | ||
iovec remote{ (void*)(ULONG_PTR)address, size }; | ||
ssize_t read = process_vm_readv(m_pid, &local, 1, &remote, 1, 0); | ||
#else | ||
assert(m_fd != -1); |
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.
@mikem8361 Any reason these are not runtime-like asserts?
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.
Only comment that sustains from @lpereira comments:
- Check if size is bigger than
IOV_MAX
. - Check if
read
is safely castable. We can't easily usesize_t
on a COM boundary, but we can check for overflows as needed.
Createdump uses the C++ assert macro everywhere so it should be ok. I really tried to keep createdump fairly pure C++ except for a couple of PAL references.
@john Salem<mailto:josalem@microsoft.com> (I think) found they didn’t seem to display any output in the runtime when hit.
|
See benchmark results in microsoft/clrmd#351