]> Cypherpunks repositories - gostls13.git/commitdiff
runtime/cgo: retry _beginthread on EACCES
authorMichael Pratt <mpratt@google.com>
Fri, 3 Jun 2022 20:22:58 +0000 (16:22 -0400)
committerMichael Pratt <mpratt@google.com>
Thu, 9 Jun 2022 18:17:45 +0000 (18:17 +0000)
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 <mknyszek@google.com>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Michael Pratt <mpratt@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>

src/runtime/cgo/gcc_libinit_windows.c

index a9b94c37139b446cb5d506c18f8d249d7a1ec122..2b5896bb221c6c1cade68ec1b6b13dbc56e5ee53 100644 (file)
@@ -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();
 }