aboutsummaryrefslogtreecommitdiff
path: root/compiler_wrapper
diff options
context:
space:
mode:
authorGeorge Burgess IV <gbiv@google.com>2020-06-18 18:10:27 -0700
committerGeorge Burgess <gbiv@chromium.org>2020-06-20 01:50:41 +0000
commit83785c35e6d23abd24d30cc5eab36b0561b8eb5b (patch)
treee0cb6b836b21f861ab942ae2c1a52471a245e776 /compiler_wrapper
parent2efe72e635474b402b4cd456f51c0bc5989931aa (diff)
downloadtoolchain-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.go22
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{}