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

createdump can read memory with process_vm_readv on Linux #420

Merged
merged 2 commits into from Jan 28, 2020

Conversation

nxtn
Copy link
Contributor

@nxtn nxtn commented Dec 1, 2019

See benchmark results in microsoft/clrmd#351

@nxtn
Copy link
Contributor Author

nxtn commented Dec 1, 2019

This system call was added in Linux 3.2, which requires at least RHEL 7.

@jkotas
Copy link
Member

jkotas commented Dec 1, 2019

We should drop support for RHEL6 for .NET 5. Opened #423

@0xd4d
Copy link

0xd4d commented Dec 1, 2019

Will probably also fix dotnet/diagnostics#548

Copy link
Contributor

@lpereira lpereira left a 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);
Copy link
Contributor

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.)

Copy link
Contributor

@lpereira lpereira Dec 2, 2019

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.

Copy link
Member

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.

Copy link
Contributor Author

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.

Copy link
Contributor Author

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!

Copy link
Contributor Author

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.

Copy link
Member

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.

@nxtn nxtn changed the title createdump can read memory with process_vm_readv createdump can read memory with process_vm_readv on Linux Dec 3, 2019
@@ -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
Copy link
Member

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.

@hoyosjs
Copy link
Member

hoyosjs commented Dec 6, 2019

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.

@lpereira lpereira dismissed their stale review December 10, 2019 17:39

Conversations have been resolved.

@hoyosjs
Copy link
Member

hoyosjs commented Jan 28, 2020

/azp run

@azure-pipelines
Copy link

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.

@hoyosjs
Copy link
Member

hoyosjs commented Jan 28, 2020

/azp list

@hoyosjs
Copy link
Member

hoyosjs commented Jan 28, 2020

/azp run runtime

@hoyosjs hoyosjs self-requested a review January 28, 2020 18:41
@ghost
Copy link

ghost commented Jan 28, 2020

Hello @hoyosjs!

Because this pull request has the auto-merge label, I will be glad to assist with helping to merge this pull request once all check-in policies pass.

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 (@msftbot) and give me an instruction to get started! Learn more here.

@azure-pipelines
Copy link

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);
Copy link
Member

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?

Copy link
Member

@hoyosjs hoyosjs left a 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 use size_t on a COM boundary, but we can check for overflows as needed.

@mikem8361
Copy link
Member

mikem8361 commented Jan 28, 2020 via email

@hoyosjs hoyosjs merged commit 531feac into dotnet:master Jan 28, 2020
@nxtn nxtn deleted the createdump branch January 29, 2020 02:51
@ghost ghost locked as resolved and limited conversation to collaborators Dec 11, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants