From c7ccabf3fea67f002bef190a5ffc7417f4371a23 Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Fri, 3 Jun 2022 16:22:58 -0400 Subject: [PATCH] runtime/cgo: retry _beginthread on EACCES We occassionally see _beginthread failing with EACCES, meaning "insufficient resources" according to the Microsoft documentation. Exactly which resources is unclear. Similar to pthread_create on unix systems, we can wait a bit and retry to try to get success. The alternative is to abort, so we may as well give it a try. Fixes #52572. Change-Id: I6e05add53b4ae36c61e53b1ee3fed6bc74e17dfa Reviewed-on: https://go-review.googlesource.com/c/go/+/410355 Reviewed-by: Michael Knyszek Reviewed-by: Ian Lance Taylor Run-TryBot: Michael Pratt TryBot-Result: Gopher Robot --- src/runtime/cgo/gcc_libinit_windows.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/runtime/cgo/gcc_libinit_windows.c b/src/runtime/cgo/gcc_libinit_windows.c index a9b94c37139..2b5896bb221 100644 --- a/src/runtime/cgo/gcc_libinit_windows.c +++ b/src/runtime/cgo/gcc_libinit_windows.c @@ -129,11 +129,23 @@ void (*(_cgo_get_context_function(void)))(struct context_arg*) { } void _cgo_beginthread(void (*func)(void*), void* arg) { + int tries; uintptr_t thandle; - thandle = _beginthread(func, 0, arg); - if (thandle == -1) { - fprintf(stderr, "runtime: failed to create new OS thread (%d)\n", errno); - abort(); + for (tries = 0; tries < 20; tries++) { + thandle = _beginthread(func, 0, arg); + if (thandle == -1 && errno == EACCES) { + // "Insufficient resources", try again in a bit. + // + // Note that the first Sleep(0) is a yield. + Sleep(tries); // milliseconds + continue; + } else if (thandle == -1) { + break; + } + return; // Success! } + + fprintf(stderr, "runtime: failed to create new OS thread (%d)\n", errno); + abort(); }