[master] 84b14ba Wrap the testable VRND in program supplied locking, because it is not thread-safe.

Poul-Henning Kamp phk at FreeBSD.org
Wed Jun 6 13:44:16 UTC 2018


commit 84b14baa085d6d20051bb8af04af09e3c466aa76
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date:   Wed Jun 6 13:42:51 2018 +0000

    Wrap the testable VRND in program supplied locking, because it
    is not thread-safe.
    
    Switch from random(3) to testable VRND for same reason.

diff --git a/bin/varnishd/cache/cache_esi_fetch.c b/bin/varnishd/cache/cache_esi_fetch.c
index acc1104..b1f993d 100644
--- a/bin/varnishd/cache/cache_esi_fetch.c
+++ b/bin/varnishd/cache/cache_esi_fetch.c
@@ -39,6 +39,8 @@
 
 #include "cache_esi.h"
 
+#include "vrnd.h"
+
 /*---------------------------------------------------------------------
  */
 
@@ -198,7 +200,7 @@ vfp_esi_gzip_pull(struct vfp_ctx *vc, struct vfp_entry *vfe, void *p,
 	*lp = 0;
 	l = vef->ibuf_sz - (vef->ibuf_i - vef->ibuf);
 	if (DO_DEBUG(DBG_ESI_CHOP)) {
-		d = (random() & 3) + 1;
+		d = (VRND_RandomTestable() & 3) + 1;
 		if (d < l)
 			l = d;
 	}
@@ -259,7 +261,7 @@ vfp_esi_pull(struct vfp_ctx *vc, struct vfp_entry *vfe, void *p, ssize_t *lp)
 	AN(p);
 	AN(lp);
 	if (DO_DEBUG(DBG_ESI_CHOP)) {
-		d = (random() & 3) + 1;
+		d = (VRND_RandomTestable() & 3) + 1;
 		if (d < *lp)
 			*lp = d;
 	}
diff --git a/bin/varnishd/cache/cache_main.c b/bin/varnishd/cache/cache_main.c
index 8b7a63e..4683a3f 100644
--- a/bin/varnishd/cache/cache_main.c
+++ b/bin/varnishd/cache/cache_main.c
@@ -52,6 +52,19 @@
 
 
 volatile struct params		*cache_param;
+static pthread_mutex_t		cache_vrnd_mtx;
+
+static void
+cache_vrnd_lock(void)
+{
+	AZ(pthread_mutex_lock(&cache_vrnd_mtx));
+}
+
+static void
+cache_vrnd_unlock(void)
+{
+	AZ(pthread_mutex_unlock(&cache_vrnd_mtx));
+}
 
 /*--------------------------------------------------------------------
  * Per thread storage for the session currently being processed by
@@ -339,6 +352,10 @@ child_main(int sigmagic, size_t altstksz)
 
 	THR_SetName("cache-main");
 
+	AZ(pthread_mutex_init(&cache_vrnd_mtx, NULL));
+	VRND_Lock = cache_vrnd_lock;
+	VRND_Unlock = cache_vrnd_unlock;
+
 	VSM_Init();	/* First, LCK needs it. */
 
 	LCK_Init();	/* Second, locking */
diff --git a/bin/varnishtest/vtc.c b/bin/varnishtest/vtc.c
index 69b2d3d..2765665 100644
--- a/bin/varnishtest/vtc.c
+++ b/bin/varnishtest/vtc.c
@@ -40,6 +40,7 @@
 #include "vtc.h"
 
 #include "vav.h"
+#include "vrnd.h"
 #include "vtim.h"
 
 #define		MAX_TOKENS		200
@@ -50,6 +51,20 @@ pthread_t		vtc_thread;
 int			ign_unknown_macro = 0;
 static struct vtclog	*vltop;
 
+static pthread_mutex_t	vtc_vrnd_mtx;
+
+static void
+vtc_vrnd_lock(void)
+{
+	AZ(pthread_mutex_lock(&vtc_vrnd_mtx));
+}
+
+static void
+vtc_vrnd_unlock(void)
+{
+	AZ(pthread_mutex_unlock(&vtc_vrnd_mtx));
+}
+
 /**********************************************************************
  * Macro facility
  */
@@ -465,6 +480,11 @@ exec_file(const char *fn, const char *script, const char *tmpdir,
 
 	(void)signal(SIGPIPE, SIG_IGN);
 
+	AZ(pthread_mutex_init(&vtc_vrnd_mtx, NULL));
+	VRND_Lock = vtc_vrnd_lock;
+	VRND_Unlock = vtc_vrnd_unlock;
+	VRND_SeedAll();
+
 	tfn = fn;
 	vtc_loginit(logbuf, loglen);
 	vltop = vtc_logopen("top");
diff --git a/bin/varnishtest/vtc_http.c b/bin/varnishtest/vtc_http.c
index 54b2a20..741c5f1 100644
--- a/bin/varnishtest/vtc_http.c
+++ b/bin/varnishtest/vtc_http.c
@@ -45,6 +45,7 @@
 #include "vfil.h"
 #include "vgz.h"
 #include "vnum.h"
+#include "vrnd.h"
 #include "vtcp.h"
 #include "hpack.h"
 
@@ -189,7 +190,7 @@ synth_body(const char *len, int rnd)
 				k = '!';
 			l = k;
 		} else if (rnd) {
-			b[j] = (random() % 95) + ' ';
+			b[j] = (VRND_RandomTestable() % 95) + ' ';
 		} else {
 			b[j] = (char)l;
 			if (++l == '~')
@@ -1970,7 +1971,7 @@ xxx(void)
 		*ibuf = 0;
 		for (j = 0; j < 7; j++) {
 			snprintf(strchr(ibuf, 0), 5, "%x",
-			    (unsigned)random() & 0xffff);
+			    (unsigned)VRND_RandomTestable() & 0xffff);
 			vz.next_in = TRUST_ME(ibuf);
 			vz.avail_in = strlen(ibuf);
 			vz.next_out = TRUST_ME(obuf);
diff --git a/include/vrnd.h b/include/vrnd.h
index 6a89762..a828af8 100644
--- a/include/vrnd.h
+++ b/include/vrnd.h
@@ -28,7 +28,13 @@
  * Random functions
  */
 
+typedef void vrnd_lock_f(void);
+
+extern vrnd_lock_f *VRND_Lock;
+extern vrnd_lock_f *VRND_Unlock;
+
 int VRND_RandomCrypto(void *, size_t);
+
 long VRND_RandomTestable(void);
 double VRND_RandomTestableDouble(void);
 void VRND_SeedTestable(unsigned int);
diff --git a/lib/libvarnish/binary_heap.c b/lib/libvarnish/binary_heap.c
index b49f9d6..fee40c9 100644
--- a/lib/libvarnish/binary_heap.c
+++ b/lib/libvarnish/binary_heap.c
@@ -519,6 +519,11 @@ chk2(struct binheap *bh)
 }
 #endif
 
+static void
+vrnd_lock(void)
+{
+}
+
 int
 main(void)
 {
@@ -528,6 +533,9 @@ main(void)
 
 	VRND_SeedAll();
 	VRND_SeedTestable(1);
+	VRND_Lock = vrnd_lock;
+	VRND_Unlock = vrnd_lock;
+
 	bh = binheap_new(NULL, cmp, update);
 	for (n = 2; n; n += n) {
 		child(bh, n - 1, &u, &v);
diff --git a/lib/libvarnish/vrnd.c b/lib/libvarnish/vrnd.c
index 3dc8b18..13557b0 100644
--- a/lib/libvarnish/vrnd.c
+++ b/lib/libvarnish/vrnd.c
@@ -45,6 +45,10 @@
 #include "vas.h"
 #include "vrnd.h"
 
+
+vrnd_lock_f *VRND_Lock;
+vrnd_lock_f *VRND_Unlock;
+
 /**********************************************************************
  * Stripped down random(3) implementation from FreeBSD, to provide
  * predicatable "random" numbers of testing purposes.
@@ -96,23 +100,8 @@ good_rand(uint32_t ctx)
 	return (x - 1);
 }
 
-void
-VRND_SeedTestable(unsigned int x)
-{
-	int i, lim;
-
-	state[0] = (uint32_t)x;
-	for (i = 1; i < rand_deg; i++)
-		state[i] = good_rand(state[i - 1]);
-	fptr = &state[rand_sep];
-	rptr = &state[0];
-	lim = 10 * rand_deg;
-	for (i = 0; i < lim; i++)
-		(void)VRND_RandomTestable();
-}
-
-long
-VRND_RandomTestable(void)
+static long
+vrnd_RandomTestable(void)
 {
 	uint32_t i;
 	uint32_t *f, *r;
@@ -135,6 +124,35 @@ VRND_RandomTestable(void)
 	return ((long)i);
 }
 
+
+void
+VRND_SeedTestable(unsigned int x)
+{
+	int i, lim;
+
+	state[0] = (uint32_t)x;
+	for (i = 1; i < rand_deg; i++)
+		state[i] = good_rand(state[i - 1]);
+	fptr = &state[rand_sep];
+	rptr = &state[0];
+	lim = 10 * rand_deg;
+	for (i = 0; i < lim; i++)
+		(void)vrnd_RandomTestable();
+}
+
+long
+VRND_RandomTestable(void)
+{
+	long l;
+
+	AN(VRND_Lock);
+	VRND_Lock();
+	l = vrnd_RandomTestable();
+	AN(VRND_Unlock);
+	VRND_Unlock();
+	return (l);
+}
+
 double
 VRND_RandomTestableDouble(void)
 {


More information about the varnish-commit mailing list