-
-
Notifications
You must be signed in to change notification settings - Fork 2.5k
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
std.process.Child: implement maxrss on Darwin #15050
Conversation
Turns out iOS does not match the OSX implementation (related node GH issue, and libuv solution PR):
Will get a simulator up for .ios, .watchos, .tvos to verify the archived man paged still applies to those. |
Turns out the archived page is wrong. Darwin is consistent across apple platforms for I verified this on iOS simulator (see code block below). One complication is that on iOS the first wait4 call is always interrupted leaving garbage values in rusage. However, the second time around it succeeds. Discovered through how Swift uses But, The fact fork works in iOS simulator is odd, maybe the sandbox is disabled for performance reasons. I still think the best option is to set these other Darwin targets as unable to spawn and generate compile errors. This will allow reverting back to switch cases for For completeness, here is the C code ran through Xcode that verifies iOS also returns maxrss in bytes. The same code was run on MacOS by compiling with clang (no Xcode project was created). Code and results from macOS and iOS simulator, `wait4` perror is logged once for iOS simulator but never for macOS.#include <assert.h>
#include <sys/errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/resource.h>
int main(int argc, char * argv[]) {
pid_t pid = fork();
if (pid == 0) {
// Child process
size_t mem_size = (20 * 1024 * 1024); // Allocate 20MB of memory
// maxrss results:
// (MB granularity to ensure underlying allocator always grabs
// different amount of pages):
// mem_size macOS iOS
// 1MB 1417216 2273280
// 4MB 4571136 5455872
// 10MB 10862592 11714560
// 20MB 21348352 22167552
char* mem = malloc(mem_size);
if (mem == NULL) {
perror("malloc");
exit(1);
}
// Use the memory to ensure it's not optimized away
for (size_t i = 0; i < mem_size; i++) {
mem[i] = i % 256;
}
sleep(1); // simulate some work
free(mem);
printf("Child exiting\n");
exit(0);
} else if (pid > 0) {
// Parent process
// From Swift example https://github.com/apple/swift/blob/dfcc4fce9883ac9989eef9893651a780bad88cb4/lib/Basic/Unix/TaskQueue.inc#L599-L619
int Status = 0;
struct rusage Usage;
for (;;) {
// NOTE: only succeeds second time for iOS, need for loop
const pid_t pidFromWait = wait4(pid, &Status, 0, &Usage);
if (pidFromWait == pid)
break;
assert(pidFromWait == -1 &&
"Did not pass WNOHANG, should only get pidToWaitFor or -1");
if (errno == ECHILD || errno == EINVAL)
exit(1);
else {
perror("wait4");
}
}
int exit_status = WEXITSTATUS(Status);
printf("Child process terminated with status %d\n", exit_status);
printf("User time used: %ld.%06d s\n", Usage.ru_utime.tv_sec, Usage.ru_utime.tv_usec);
printf("System time used: %ld.%06d s\n", Usage.ru_stime.tv_sec, Usage.ru_stime.tv_usec);
printf("Max RSS: %ld\n", Usage.ru_maxrss);
} else {
// Fork failed
perror("fork");
exit(1);
}
} |
For the future, official Apple OSS distributions can be found here: https://github.com/apple-oss-distributions |
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.
Nice work! I've got a couple nits and then i think we can go ahead and merge it. When it comes to iOS and other Apple platforms, I don't think anyone would want to spawn a child process using this API for the reasons you mentioned. I believe that for those platforms Apple prescribes you use their frameworks more than anything else. Having said that even if you could spawn a child with this API and it didn't work, we can always revisit later for better iOS support (and other Apple platforms).
1f123be
to
43c50f8
Compare
Updated with your comments in mind! Did not split the switch cases since they share the same implementation. |
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.
Looks great, thanks!
Can you resolve conflicts with the master branch please? |
Notably the Darwin (XNU) kernel the maxrss field is number of bytes and not kilobytes (kibibytes) like other platforms (e.g. Linux, BSD). watchOS and tvOS are not supported because they do not have the ability to spawn a child process. iOS is enabled but due to OS sandboxing it should fail with a permission error.
43c50f8
to
25a0896
Compare
Rebased and resolved! @kubkon |
Notably the Darwin (XNU) kernel the maxrss field is number of bytes and not kilobytes (kibibytes) like other platforms (e.g. Linux, BSD).
This is my first PR, although very small in scope, feel welcome to give input.
Fixes #14957