[master] 36e0454e4 Work around OSX returning EINVAL to pthread_cond_timedwait()
Poul-Henning Kamp
phk at FreeBSD.org
Wed Oct 27 16:33:07 UTC 2021
commit 36e0454e460ca921ef6db3b25947868f7f99bb90
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date: Wed Oct 27 16:32:05 2021 +0000
Work around OSX returning EINVAL to pthread_cond_timedwait()
diff --git a/bin/varnishd/cache/cache_lck.c b/bin/varnishd/cache/cache_lck.c
index aeb228e46..827a12343 100644
--- a/bin/varnishd/cache/cache_lck.c
+++ b/bin/varnishd/cache/cache_lck.c
@@ -229,6 +229,34 @@ Lck_CondWaitUntil(pthread_cond_t *cond, struct lock *lck, vtim_real when)
struct ilck *ilck;
struct timespec ts;
+#if defined (__APPLE__)
+ /*
+ * I hate woo-doo programming in all it's forms and all it's
+ * manifestations, but for reasons I utterly fail to isolate
+ * yielding here is stops OSX from throwing a EINVAL to the
+ * pthread_cond_wait(3) call.
+ *
+ * I have tried very hard to determine if any of the three
+ * arguments are in fact invalid, and found nothing which
+ * even hints that it might be the case, and with high probability
+ * repeating the failed call with the exact same arguments
+ * will succeed.
+ *
+ * If you want to dive into this you can trigger the situation
+ * approx 30% of the time with:
+ *
+ * cd .../vmods && make -j check
+ *
+ * Env:
+ * Darwin Kernel Version 20.5.0:
+ * Sat May 8 05:10:31 PDT 2021;
+ * root:xnu-7195.121.3~9/RELEASE_ARM64_T8101 arm64
+ *
+ * 20211027 /phk
+ */
+ pthread_yield_np();
+#endif
+
AN(lck);
CAST_OBJ_NOTNULL(ilck, lck->priv, ILCK_MAGIC);
AN(ilck->held);
@@ -242,19 +270,6 @@ Lck_CondWaitUntil(pthread_cond_t *cond, struct lock *lck, vtim_real when)
ts = VTIM_timespec(when);
assert(ts.tv_nsec >= 0 && ts.tv_nsec <= 999999999);
errno = pthread_cond_timedwait(cond, &ilck->mtx, &ts);
-#if defined (__APPLE__)
- if (errno == EINVAL && when <= VTIM_real()) {
- /*
- * Most kernels treat this as honest error,
- * recognizing that a thread has no way to
- * prevent being descheduled between a user-
- * land check of the timestamp, and getting
- * the timestamp into the kernel before it
- * expires. OS/X on the other hand...
- */
- errno = ETIMEDOUT;
- }
-#endif
assert(errno == 0 ||
errno == ETIMEDOUT ||
errno == EINTR);
More information about the varnish-commit
mailing list