aboutsummaryrefslogtreecommitdiffstats
path: root/executor/common.h
diff options
context:
space:
mode:
Diffstat (limited to 'executor/common.h')
-rw-r--r--executor/common.h19
1 files changed, 16 insertions, 3 deletions
diff --git a/executor/common.h b/executor/common.h
index 6f11ef058..61600a712 100644
--- a/executor/common.h
+++ b/executor/common.h
@@ -241,9 +241,22 @@ static void thread_start(void* (*fn)(void*), void* arg)
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setstacksize(&attr, 128 << 10);
- if (pthread_create(&th, &attr, fn, arg))
- exitf("pthread_create failed");
- pthread_attr_destroy(&attr);
+ int i;
+ // Clone can fail spuriously with EAGAIN if there is a concurrent execve in progress.
+ // (see linux kernel commit 498052bba55ec). But it can also be a true limit imposed by cgroups.
+ // In one case we want to retry infinitely, in another -- fail immidiately...
+ for (i = 0; i < 100; i++) {
+ if (pthread_create(&th, &attr, fn, arg) == 0) {
+ pthread_attr_destroy(&attr);
+ return;
+ }
+ if (errno == EAGAIN) {
+ usleep(50);
+ continue;
+ }
+ break;
+ }
+ exitf("pthread_create failed");
}
#endif