Skip to content

Prefer vfork to fork#1059

Merged
rwails merged 4 commits intoshadow:devfrom
rwails:vfork
Dec 17, 2020
Merged

Prefer vfork to fork#1059
rwails merged 4 commits intoshadow:devfrom
rwails:vfork

Conversation

@rwails
Copy link
Copy Markdown
Collaborator

@rwails rwails commented Dec 17, 2020

Changes thread_preload.c to use vfork() instead of fork() during
process creation. This change has a significant impact on experiment
performance with many (> 1000) processes to manage.
Initialization runtime is reduced by a large factor.

prctl(PR_SET_PDEATHSIG, SIGKILL) and getppid() have been moved to
the shim in _shim_load().

n.b. I believe this change does not affect ptrace mode. The prctl call
may be duplicated, but shouldn't hurt for now.

process creation. This change has a significant impact on experiment
performance with many (> 1000) processes to manage.
Initialization runtime is reduced by a large factor.

`prctl(PR_SET_PDEATHSIG, SIGKILL)` and `getppid()` have been moved to
the shim in `_shim_load()`.

n.b. I believe this change does not affect ptrace mode. The `prctl` call
may be duplicated, but shouldn't hurt for now.
@codecov
Copy link
Copy Markdown

codecov bot commented Dec 17, 2020

Codecov Report

Merging #1059 (205cc55) into dev (4cc05c3) will decrease coverage by 0.01%.
The diff coverage is 15.38%.

Impacted file tree graph

@@            Coverage Diff             @@
##              dev    #1059      +/-   ##
==========================================
- Coverage   55.07%   55.05%   -0.02%     
==========================================
  Files         127      127              
  Lines       19231    19246      +15     
  Branches     4592     4595       +3     
==========================================
+ Hits        10591    10596       +5     
- Misses       5871     5878       +7     
- Partials     2769     2772       +3     
Flag Coverage Δ
tests 55.05% <15.38%> (-0.02%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
src/main/host/thread_preload.c 0.00% <0.00%> (ø)
src/shim/shim.c 55.55% <28.57%> (-5.67%) ⬇️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 4cc05c3...26af895. Read the comment docs.

Copy link
Copy Markdown
Member

@robgjansen robgjansen left a comment

Choose a reason for hiding this comment

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

A couple of comments would be helpful :)

error("parent (shadow) exited");
return -1;
}
int rc = execvpe(file, argv, envp);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think we want a comment somewhere around here about how the code is designed so that the child process does not execute any code after the vfork and before calling exec, to guard against future programmers changing this code from accidentally causing undefined behavior.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Fixed

src/shim/shim.c Outdated
error("SHADOW_PID does not contain an unsigned: %s", shadow_pid_str);
} else {

assert((pid_t)tmp_pid == tmp_pid);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Is this vacuously true?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think it's to validate it wasn't truncated in the conversion to pid_t? +1 that it could use a comment

It'd be nice if we could parse into a pid_t directly, but I suppose that's tricky since we can't know the format specifier to provide to sscanf (without assuming something about the definition of pid_t).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

OTOH we could just not do this downcast, and compare directly. C will widen the pid if it's narrower.

unsigned long long shadow_pid = 0;
if (sscanf(shadow_pid_str, "%llu", &shadow_pid) != 1) {
...
// Implicitly widen return value of getppid
if (getppid() != shadow_pid) {

Btw this control flow would probably be a bit easier to follow by using early exits to avoid excessive nesting.

if (/* something failed */) {
  /* log and exit */
}
if (/* something else failed */) {
  /* log and exit */
}

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Fixed

char* const envp[]) {
pid_t shadow_pid = getpid();
pid_t pid = fork();
pid_t pid = vfork();
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Maybe add a short comment about why we are using vfork since moving away from it isn't a decision that should be taken lightly.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Fixed

src/shim/shim.c Outdated
error("SHADOW_PID does not contain an unsigned: %s", shadow_pid_str);
} else {

assert((pid_t)tmp_pid == tmp_pid);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think it's to validate it wasn't truncated in the conversion to pid_t? +1 that it could use a comment

It'd be nice if we could parse into a pid_t directly, but I suppose that's tricky since we can't know the format specifier to provide to sscanf (without assuming something about the definition of pid_t).

Ryan Wails added 2 commits December 17, 2020 13:07
1. Added comments warning about code between vfork + exec.

2. Noted that vfork has better performance in comments

3. Cleaned up the control flow of the parent-PID check in the shim.
@rwails rwails merged commit 931e067 into shadow:dev Dec 17, 2020
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.

3 participants