diff options
author | George Burgess IV <gbiv@google.com> | 2020-06-18 18:10:27 -0700 |
---|---|---|
committer | George Burgess <gbiv@chromium.org> | 2020-06-20 01:50:41 +0000 |
commit | 83785c35e6d23abd24d30cc5eab36b0561b8eb5b (patch) | |
tree | e0cb6b836b21f861ab942ae2c1a52471a245e776 /compiler_wrapper | |
parent | 2efe72e635474b402b4cd456f51c0bc5989931aa (diff) | |
download | toolchain-utils-83785c35e6d23abd24d30cc5eab36b0561b8eb5b.tar.gz |
wrapper: fork() before exec()ing
This CL is a wild guess that tries to work around what appears to be an
incredibly rare Go runtime bug
(https://github.com/golang/go/issues/24484). As mentioned on the
chromium bug, apparently execve is taking a while... somehow, and
`pthread_create` fails with `EAGAIN` concurrently.
So the intent here is to `fork()` + `exec()`. `fork()` will
a) dispose of the thread that's trying to `pthread_create`
b) isolate the `exec` in its own process, so the parent's runtime can
spin up as many threads as it likes in peace.
This slows down an 'ideal' kernel build (aka a build where ccache is a
100% hit rate, so the compiler wrapper's overheads are very pronounced)
by ~4% in my measurements.
BUG=chromium:1095528
TEST=sdk tryjob; CQ
Change-Id: I73e1b238738b74c85def4709c09610f586fb04e5
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/toolchain-utils/+/2252552
Reviewed-by: Manoj Gupta <manojgupta@chromium.org>
Tested-by: George Burgess <gbiv@chromium.org>
Diffstat (limited to 'compiler_wrapper')
-rw-r--r-- | compiler_wrapper/libc_exec.go | 22 |
1 files changed, 19 insertions, 3 deletions
diff --git a/compiler_wrapper/libc_exec.go b/compiler_wrapper/libc_exec.go index f8db9d86..d9867733 100644 --- a/compiler_wrapper/libc_exec.go +++ b/compiler_wrapper/libc_exec.go @@ -7,15 +7,31 @@ package main // #include <errno.h> +// #include <stdio.h> // #include <stdlib.h> // #include <string.h> // #include <unistd.h> +// #include <sys/types.h> +// #include <sys/wait.h> // // int libc_exec(const char *pathname, char *const argv[], char *const envp[]) { -// if (execve(pathname, argv, envp) != 0) { +// // Since fork() brings us to one thread, we can only use async-signal-safe funcs below. +// pid_t pid = fork(); +// if (pid == 0) { +// execve(pathname, argv, envp); +// fprintf(stderr, "exec failed (errno: %d)\n", errno); +// _exit(1); +// } +// if (pid < 0) { +// return errno; +// } +// +// int wstatus; +// pid_t waited = waitpid(pid, &wstatus, 0); +// if (waited == -1) { // return errno; // } -// return 0; +// exit(WEXITSTATUS(wstatus)); //} import "C" import ( @@ -29,7 +45,7 @@ import ( // Note that this changes the go binary to be a dynamically linked one. // See crbug.com/1000863 for details. // To use this version of exec, please add '-tags libc_exec' when building Go binary. -// Without the tags, libc_exec.go will be used. +// Without the tags, libc_exec.go will not be used. func execCmd(env env, cmd *command) error { freeList := []unsafe.Pointer{} |