Repository: fortio/fortio (go)

Issue:
Data race with parallel warmup and standard client (was Fortio crash when payload added in UI)
**Bug Description**
Adding Payload through the UI causes fortio to crash when increasing the number of threads.

***How to Reproduce***
1. Launch fortio v1.21.0 on a k8s cluster. Expose outside cluster via Ingress/VirtualService/Gateway.
Example deployment:
```
---
apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
  name: fortio-client
spec:
  replicas: 1
  revisionHistoryLimit: 10
  selector:
    matchLabels:
      app: fortio-client
  strategy:
    rollingUpdate:
      maxSurge: 25%
      maxUnavailable: 25%
    type: RollingUpdate
  template:
    metadata:
      labels:
        app: fortio-client
    spec:
      containers:
      - image: fortio/fortio:1.21.0
        imagePullPolicy: Always
        name: fortio
        ports:
        - containerPort: 8080
          name: http-fortio
          protocol: TCP
        - containerPort: 8079
          name: grpc-ping
          protocol: TCP
        resources:
          limits:
            cpu: "5"
            memory: 2Gi
          requests:
            cpu: "5"
            memory: 2Gi
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
      dnsPolicy: ClusterFirst
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext: {}
      terminationGracePeriodSeconds: 30
```
2. Browse to the UI, insert ```adsf``` in the payload testbox and test URL to an echo service like httpbin or another fortio instance to echo back.
3. Increase threads to something like 100.
4. Click Start

***What Happens?***
Fortio UI switches to the ```Running load test... Results pending...``` screen, and the progress bar hangs. Logs from instance show process crashes. - fatal error: concurrent map iteration and map write

Logs w/ stacktrace:
```
19:58:31 I httprunner.go:82> Starting http test for https://httpbin.myingress.com/post with 100 threads at 1000.0 qps
19:58:31 W http_client.go:146> https requested, switching to standard go client
fatal error: concurrent map iteration and map write

goroutine 57685 [running]:
runtime.throw({0xa39f4e, 0x0})
	/usr/local/go/src/runtime/panic.go:1198 +0x71 fp=0xc00047d4f0 sp=0xc00047d4c0 pc=0x4353b1
runtime.mapiternext(0xa27c7f)
	/usr/local/go/src/runtime/map.go:858 +0x4eb fp=0xc00047d560 sp=0xc00047d4f0 pc=0x40fa8b
net/http.(*Transport).roundTrip(0xc0000ea3c0, 0xc00043e000)
	/usr/local/go/src/net/http/transport.go:520 +0xa85 fp=0xc00047d798 sp=0xc00047d560 pc=0x6ac145
net/http.(*Transport).RoundTrip(0xc00043e000, 0xb11480)
	/usr/local/go/src/net/http/roundtrip.go:18 +0x19 fp=0xc00047d7b8 sp=0xc00047d798 pc=0x694959
net/http.send(0xc000350200, {0xb11480, 0xc0000ea3c0}, {0xa0d6a0, 0x4bb501, 0xef5180})
	/usr/local/go/src/net/http/client.go:252 +0x5d8 fp=0xc00047d998 sp=0xc00047d7b8 pc=0x654fd8
net/http.(*Client).send(0xc0004cccf0, 0xc000350200, {0x0, 0x0, 0xef5180})
	/usr/local/go/src/net/http/client.go:176 +0x9b fp=0xc00047da10 sp=0xc00047d998 pc=0x65487b
net/http.(*Client).do(0xc0004cccf0, 0xc000350200)
	/usr/local/go/src/net/http/client.go:725 +0x908 fp=0xc00047dc10 sp=0xc00047da10 pc=0x656cc8
net/http.(*Client).Do(...)
	/usr/local/go/src/net/http/client.go:593
fortio.org/fortio/fhttp.(*Client).Fetch(0xc00012e0e0)
	/go/src/fortio.org/fortio/fhttp/http_client.go:374 +0x7b fp=0xc00047de60 sp=0xc00047dc10 pc=0x78855b
fortio.org/fortio/fhttp.RunHTTPTest.func1()
	/go/src/fortio.org/fortio/fhttp/httprunner.go:112 +0x73 fp=0xc00047df78 sp=0xc00047de60 pc=0x7976f3
fortio.org/fortio/fhttp.(*errgroup).Go.func1()
	/go/src/fortio.org/fortio/fhttp/httprunner.go:220 +0x63 fp=0xc00047dfe0 sp=0xc00047df78 pc=0x797b03
runtime.goexit()
	/usr/local/go/src/runtime/asm_amd64.s:1581 +0x1 fp=0xc00047dfe8 sp=0xc00047dfe0 pc=0x468201
created by fortio.org/fortio/fhttp.(*errgroup).Go
	/go/src/fortio.org/fortio/fhttp/httprunner.go:217 +0x88

goroutine 1 [select (no cases), 23 minutes]:
main.serverLoop({0x0, 0x1})
	/go/src/fortio.org/fortio/fortio_main.go:300 +0x1e5
main.main()
	/go/src/fortio.org/fortio/fortio_main.go:284 +0xb57

goroutine 33 [syscall, 23 minutes]:
syscall.Syscall6(0xe8, 0x7, 0xc00028fbec, 0x7, 0xffffffffffffffff, 0x0, 0x0)
	/usr/local/go/src/syscall/asm_linux_amd64.s:43 +0x5
golang.org/x/sys/unix.EpollWait(0x0, {0xc00028fbec, 0x0, 0x0}, 0x0)
	/go/pkg/mod/golang.org/x/sys@v0.0.0-20211216021012-1d35b9e2eb4e/unix/zsyscall_linux_amd64.go:56 +0x58
github.com/fsnotify/fsnotify.(*fdPoller).wait(0xc000226020)
	/go/pkg/mod/github.com/fsnotify/fsnotify@v1.5.1/inotify_poller.go:87 +0x7d
github.com/fsnotify/fsnotify.(*Watcher).readEvents(0xc00022e000)
	/go/pkg/mod/github.com/fsnotify/fsnotify@v1.5.1/inotify.go:193 +0x2b0
created by github.com/fsnotify/fsnotify.NewWatcher
	/go/pkg/mod/github.com/fsnotify/fsnotify@v1.5.1/inotify.go:60 +0x1c7

goroutine 34 [select, 23 minutes]:
fortio.org/fortio/dflag/configmap.(*Updater).watchForUpdates(0xc00021ce40)
	/go/src/fortio.org/fortio/dflag/configmap/updater.go:159 +0xce
created by fortio.org/fortio/dflag/configmap.(*Updater).Start
	/go/src/fortio.org/fortio/dflag/configmap/updater.go:95 +0x2bd

goroutine 35 [IO wait, 23 minutes]:
internal/poll.runtime_pollWait(0x7f9629fc83e0, 0x72)
	/usr/local/go/src/runtime/netpoll.go:234 +0x89
internal/poll.(*pollDesc).wait(0xc000216180, 0x0, 0x0)
	/usr/local/go/src/internal/poll/fd_poll_runtime.go:84 +0x32
internal/poll.(*pollDesc).waitRead(...)
	/usr/local/go/src/internal/poll/fd_poll_runtime.go:89
internal/poll.(*FD).Accept(0xc000216180)
	/usr/local/go/src/internal/poll/fd_unix.go:402 +0x22c
net.(*netFD).accept(0xc000216180)
	/usr/local/go/src/net/fd_unix.go:173 +0x35
net.(*TCPListener).accept(0xc00021a0f0)
	/usr/local/go/src/net/tcpsock_posix.go:140 +0x28
net.(*TCPListener).Accept(0xc00021a0f0)
	/usr/local/go/src/net/tcpsock.go:262 +0x3d
fortio.org/fortio/fnet.TCPEchoServer.func1()
	/go/src/fortio.org/fortio/fnet/network.go:156 +0x5c
created by fortio.org/fortio/fnet.TCPEchoServer
	/go/src/fortio.org/fortio/fnet/network.go:153 +0xbf

goroutine 36 [IO wait, 23 minutes]:
internal/poll.runtime_pollWait(0x7f9629fc82f8, 0x72)
	/usr/local/go/src/runtime/netpoll.go:234 +0x89
internal/poll.(*pollDesc).wait(0xc000216280, 0xc0002ec000, 0x0)
	/usr/local/go/src/internal/poll/fd_poll_runtime.go:84 +0x32
internal/poll.(*pollDesc).waitRead(...)
	/usr/local/go/src/internal/poll/fd_poll_runtime.go:89
internal/poll.(*FD).ReadFrom(0xc000216280, {0xc0002ec000, 0x800, 0x800})
	/usr/local/go/src/internal/poll/fd_unix.go:223 +0x238
net.(*netFD).readFrom(0xc000216280, {0xc0002ec000, 0x0, 0x0})
	/usr/local/go/src/net/fd_posix.go:62 +0x29
net.(*UDPConn).readFrom(0xc000048400, {0xc0002ec000, 0x0, 0x0}, 0xc0002ee000)
	/usr/local/go/src/net/udpsock_posix.go:47 +0x3e
net.(*UDPConn).readFromUDP(0xc000210040, {0xc0002ec000, 0x0, 0x0}, 0x0)
	/usr/local/go/src/net/udpsock.go:116 +0x31
net.(*UDPConn).ReadFromUDP(...)
	/usr/local/go/src/net/udpsock.go:108
fortio.org/fortio/fnet.UDPEchoServer.func1()
	/go/src/fortio.org/fortio/fnet/network.go:188 +0xa5
created by fortio.org/fortio/fnet.UDPEchoServer
	/go/src/fortio.org/fortio/fnet/network.go:184 +0x126

goroutine 37 [IO wait, 23 minutes]:
internal/poll.runtime_pollWait(0x7f9629fc8210, 0x72)
	/usr/local/go/src/runtime/netpoll.go:234 +0x89
internal/poll.(*pollDesc).wait(0xc000216300, 0x8, 0x0)
	/usr/local/go/src/internal/poll/fd_poll_runtime.go:84 +0x32
internal/poll.(*pollDesc).waitRead(...)
	/usr/local/go/src/internal/poll/fd_poll_runtime.go:89
internal/poll.(*FD).Accept(0xc000216300)
	/usr/local/go/src/internal/poll/fd_unix.go:402 +0x22c
net.(*netFD).accept(0xc000216300)
	/usr/local/go/src/net/fd_unix.go:173 +0x35
net.(*TCPListener).accept(0xc00021a108)
	/usr/local/go/src/net/tcpsock_posix.go:140 +0x28
net.(*TCPListener).Accept(0xc00021a108)
	/usr/local/go/src/net/tcpsock.go:262 +0x3d
google.golang.org/grpc.(*Server).Serve(0xc000256000, {0xb1e110, 0xc00021a108})
	/go/pkg/mod/google.golang.org/grpc@v1.44.0/server.go:779 +0x362
fortio.org/fortio/fgrpc.PingServer.func1()
	/go/src/fortio.org/fortio/fgrpc/pingsrv.go:87 +0x25
created by fortio.org/fortio/fgrpc.PingServer
	/go/src/fortio.org/fortio/fgrpc/pingsrv.go:86 +0x665

goroutine 38 [IO wait, 23 minutes]:
internal/poll.runtime_pollWait(0x7f9629fc8128, 0x72)
	/usr/local/go/src/runtime/netpoll.go:234 +0x89
internal/poll.(*pollDesc).wait(0xc000216380, 0x2, 0x0)
	/usr/local/go/src/internal/poll/fd_poll_runtime.go:84 +0x32
internal/poll.(*pollDesc).waitRead(...)
	/usr/local/go/src/internal/poll/fd_poll_runtime.go:89
internal/poll.(*FD).Accept(0xc000216380)
	/usr/local/go/src/internal/poll/fd_unix.go:402 +0x22c
net.(*netFD).accept(0xc000216380)
	/usr/local/go/src/net/fd_unix.go:173 +0x35
net.(*TCPListener).accept(0xc00021a138)
	/usr/local/go/src/net/tcpsock_posix.go:140 +0x28
net.(*TCPListener).Accept(0xc00021a138)
	/usr/local/go/src/net/tcpsock.go:262 +0x3d
net/http.(*Server).Serve(0xc00025a000, {0xb1e110, 0xc00021a138})
	/usr/local/go/src/net/http/server.go:3002 +0x394
fortio.org/fortio/fhttp.HTTPServer.func1()
	/go/src/fortio.org/fortio/fhttp/http_server.go:177 +0x5b
created by fortio.org/fortio/fhttp.HTTPServer
	/go/src/fortio.org/fortio/fhttp/http_server.go:176 +0x1ef

goroutine 39 [IO wait, 20 minutes]:
internal/poll.runtime_pollWait(0x7f9629fc8040, 0x72)
	/usr/local/go/src/runtime/netpoll.go:234 +0x89
internal/poll.(*pollDesc).wait(0xc000216400, 0xc000033800, 0x0)
	/usr/local/go/src/internal/poll/fd_poll_runtime.go:84 +0x32
internal/poll.(*pollDesc).waitRead(...)
	/usr/local/go/src/internal/poll/fd_poll_runtime.go:89
internal/poll.(*FD).Accept(0xc000216400)
	/usr/local/go/src/internal/poll/fd_unix.go:402 +0x22c
net.(*netFD).accept(0xc000216400)
	/usr/local/go/src/net/fd_unix.go:173 +0x35
net.(*TCPListener).accept(0xc00021a168)
	/usr/local/go/src/net/tcpsock_posix.go:140 +0x28
net.(*TCPListener).Accept(0xc00021a168)
	/usr/local/go/src/net/tcpsock.go:262 +0x3d
net/http.(*Server).Serve(0xc00025a0e0, {0xb1e110, 0xc00021a168})
	/usr/local/go/src/net/http/server.go:3002 +0x394
fortio.org/fortio/fhttp.HTTPServer.func1()
	/go/src/fortio.org/fortio/fhttp/http_server.go:177 +0x5b
created by fortio.org/fortio/fhttp.HTTPServer
	/go/src/fortio.org/fortio/fhttp/http_server.go:176 +0x1ef

goroutine 26 [syscall, 23 minutes]:
os/signal.signal_recv()
	/usr/local/go/src/runtime/sigqueue.go:169 +0x98
os/signal.loop()
	/usr/local/go/src/os/signal/signal_unix.go:24 +0x19
created by os/signal.Notify.func1.1
	/usr/local/go/src/os/signal/signal.go:151 +0x2c

goroutine 57627 [select]:
net.(*Resolver).lookupIPAddr(0xef43a0, {0xb20348, 0xc0003fa2a0}, {0xa20010, 0x203000}, {0xc00023e080, 0x31})
	/usr/local/go/src/net/lookup.go:302 +0x5c7
net.(*Resolver).internetAddrList(0xb20348, {0xb20348, 0xc0003fa2a0}, {0xa20010, 0x3}, {0xc00023e080, 0x35})
	/usr/local/go/src/net/ipsock.go:288 +0x67a
net.(*Resolver).resolveAddrList(0xf25540, {0xb20348, 0xc0003fa2a0}, {0xa20570, 0x4}, {0xa20010, 0xc080655a05e2dd66}, {0xc00023e080, 0x35}, {0x0, ...})
	/usr/local/go/src/net/dial.go:221 +0x41b
net.(*Dialer).DialContext(0xc00046d988, {0xb20348, 0xc0003fa2a0}, {0xa20010, 0x203000}, {0xc00023e080, 0x7f9650de7a68})
	/usr/local/go/src/net/dial.go:406 +0x448
fortio.org/fortio/fhttp.NewStdClient.func1({0xb20348, 0xc0003fa2a0}, {0xa20010, 0x60}, {0xc00023e080, 0x50cb73})
	/go/src/fortio.org/fortio/fhttp/http_client.go:438 +0x165
net/http.(*Transport).dial(0xc0003fa2a0, {0xb20348, 0xc0003fa2a0}, {0xa20010, 0x18}, {0xc00023e080, 0xc0004ac040})
	/usr/local/go/src/net/http/transport.go:1166 +0xda
net/http.(*Transport).dialConn(0xc000168000, {0xb20348, 0xc0003fa2a0}, {{}, 0x0, {0xc00050c180, 0x5}, {0xc00023e080, 0x35}, 0x0})
	/usr/local/go/src/net/http/transport.go:1604 +0x845
net/http.(*Transport).dialConnFor(0x5a02cd, 0xc0005300b0)
	/usr/local/go/src/net/http/transport.go:1446 +0xb0
created by net/http.(*Transport).queueForDial
	/usr/local/go/src/net/http/transport.go:1415 +0x3d7

goroutine 57702 [runnable]:
fortio.org/fortio/fhttp.(*errgroup).Go.func1()
	/go/src/fortio.org/fortio/fhttp/httprunner.go:217
created by fortio.org/fortio/fhttp.(*errgroup).Go
	/go/src/fortio.org/fortio/fhttp/httprunner.go:217 +0x88

goroutine 57701 [runnable]:
fortio.org/fortio/fhttp.(*errgroup).Go.func1()
	/go/src/fortio.org/fortio/fhttp/httprunner.go:217
created by fortio.org/fortio/fhttp.(*errgroup).Go
	/go/src/fortio.org/fortio/fhttp/httprunner.go:217 +0x88

goroutine 57709 [select]:
net/http.(*Transport).getConn(0xc000168780, 0xc000522140, {{}, 0x0, {0xc00050c180, 0x5}, {0xc000028100, 0x35}, 0x0})
	/usr/local/go/src/net/http/transport.go:1372 +0x5d2
net/http.(*Transport).roundTrip(0xc000168780, 0xc0006d0200)
	/usr/local/go/src/net/http/transport.go:581 +0x774
net/http.(*Transport).RoundTrip(0xc0006d0200, 0xb11480)
	/usr/local/go/src/net/http/roundtrip.go:18 +0x19
net/http.send(0xc000351a00, {0xb11480, 0xc000168780}, {0xa0d6a0, 0x4bb501, 0xef5180})
	/usr/local/go/src/net/http/client.go:252 +0x5d8
net/http.(*Client).send(0xc00014bad0, 0xc000351a00, {0x50cb73, 0x118, 0xef5180})
	/usr/local/go/src/net/http/client.go:176 +0x9b
net/http.(*Client).do(0xc00014bad0, 0xc000351a00)
	/usr/local/go/src/net/http/client.go:725 +0x908
net/http.(*Client).Do(...)
	/usr/local/go/src/net/http/client.go:593
fortio.org/fortio/fhttp.(*Client).Fetch(0xc00012ec40)
	/go/src/fortio.org/fortio/fhttp/http_client.go:374 +0x7b
fortio.org/fortio/fhttp.RunHTTPTest.func1()
	/go/src/fortio.org/fortio/fhttp/httprunner.go:112 +0x73
fortio.org/fortio/fhttp.(*errgroup).Go.func1()
	/go/src/fortio.org/fortio/fhttp/httprunner.go:220 +0x63
created by fortio.org/fortio/fhttp.(*errgroup).Go
	/go/src/fortio.org/fortio/fhttp/httprunner.go:217 +0x88

goroutine 57706 [runnable]:
fortio.org/fortio/fhttp.(*errgroup).Go.func1()
	/go/src/fortio.org/fortio/fhttp/httprunner.go:217
created by fortio.org/fortio/fhttp.(*errgroup).Go
	/go/src/fortio.org/fortio/fhttp/httprunner.go:217 +0x88

goroutine 57697 [runnable]:
fortio.org/fortio/fhttp.(*errgroup).Go.func1()
	/go/src/fortio.org/fortio/fhttp/httprunner.go:217
created by fortio.org/fortio/fhttp.(*errgroup).Go
	/go/src/fortio.org/fortio/fhttp/httprunner.go:217 +0x88

goroutine 57689 [select]:
net/http.(*Transport).getConn(0xc0000eaa00, 0xc0003ba140, {{}, 0x0, {0xc00050c180, 0x5}, {0xc0000d4440, 0x35}, 0x0})
	/usr/local/go/src/net/http/transport.go:1372 +0x5d2
net/http.(*Transport).roundTrip(0xc0000eaa00, 0xc000198200)
	/usr/local/go/src/net/http/transport.go:581 +0x774
net/http.(*Transport).RoundTrip(0xc000198200, 0xb11480)
	/usr/local/go/src/net/http/roundtrip.go:18 +0x19
net/http.send(0xc000350600, {0xb11480, 0xc0000eaa00}, {0xa0d6a0, 0x4bb501, 0xef5180})
	/usr/local/go/src/net/http/client.go:252 +0x5d8
net/http.(*Client).send(0xc0004cd170, 0xc000350600, {0x50cb73, 0x118, 0xef5180})
	/usr/local/go/src/net/http/client.go:176 +0x9b
net/http.(*Client).do(0xc0004cd170, 0xc000350600)
	/usr/local/go/src/net/http/client.go:725 +0x908
net/http.(*Client).Do(...)
	/usr/local/go/src/net/http/client.go:593
fortio.org/fortio/fhttp.(*Client).Fetch(0xc00012e2a0)
	/go/src/fortio.org/fortio/fhttp/http_client.go:374 +0x7b
fortio.org/fortio/fhttp.RunHTTPTest.func1()
	/go/src/fortio.org/fortio/fhttp/httprunner.go:112 +0x73
fortio.org/fortio/fhttp.(*errgroup).Go.func1()
	/go/src/fortio.org/fortio/fhttp/httprunner.go:220 +0x63
created by fortio.org/fortio/fhttp.(*errgroup).Go
	/go/src/fortio.org/fortio/fhttp/httprunner.go:217 +0x88

goroutine 57721 [runnable]:
fortio.org/fortio/fhttp.(*errgroup).Go.func1()
	/go/src/fortio.org/fortio/fhttp/httprunner.go:217
created by fortio.org/fortio/fhttp.(*errgroup).Go
	/go/src/fortio.org/fortio/fhttp/httprunner.go:217 +0x88

goroutine 57690 [runnable]:
fortio.org/fortio/fhttp.(*errgroup).Go.func1()
	/go/src/fortio.org/fortio/fhttp/httprunner.go:217
created by fortio.org/fortio/fhttp.(*errgroup).Go
	/go/src/fortio.org/fortio/fhttp/httprunner.go:217 +0x88

goroutine 56971 [runnable]:
net/http.(*Transport).queueForDial·dwrap·112()
	/usr/local/go/src/net/http/transport.go:1415
runtime.goexit()
	/usr/local/go/src/runtime/asm_amd64.s:1581 +0x1
created by net/http.(*Transport).queueForDial
	/usr/local/go/src/net/http/transport.go:1415 +0x3d7

goroutine 57729 [runnable]:
net.(*Resolver).goLookupIPCNAMEOrder.func3({0xc0001b83c0, 0x32}, 0x1)
	/usr/local/go/src/net/dnsclient_unix.go:608 +0x71
net.(*Resolver).goLookupIPCNAMEOrder(_, {_, _}, {_, _}, {_, _}, _)
	/usr/local/go/src/net/dnsclient_unix.go:621 +0x716
net.(*Resolver).lookupIP(0xef43a0, {0xb202d8, 0xc0004b8100}, {0xa20010, 0x3}, {0xc0001b82c0, 0x31})
	/usr/local/go/src/net/lookup_unix.go:103 +0x13a
net.glob..func1({0xb202d8, 0xc0004b8100}, 0xc00022e0f0, {0xa20010, 0x46616e}, {0xc0001b82c0, 0x6b0d50})
	/usr/local/go/src/net/hook.go:23 +0x3d
net.(*Resolver).lookupIPAddr.func1()
	/usr/local/go/src/net/lookup.go:296 +0x9f
internal/singleflight.(*Group).doCall(0xef43b0, 0xc00022e410, {0xc0001b8300, 0x35}, 0xc000258160)
	/usr/local/go/src/internal/singleflight/singleflight.go:95 +0x3b
created by internal/singleflight.(*Group).DoChan
	/usr/local/go/src/internal/singleflight/singleflight.go:88 +0x2f1

goroutine 57707 [runnable]:
fortio.org/fortio/fhttp.(*errgroup).Go.func1()
	/go/src/fortio.org/fortio/fhttp/httprunner.go:217
created by fortio.org/fortio/fhttp.(*errgroup).Go
	/go/src/fortio.org/fortio/fhttp/httprunner.go:217 +0x88

goroutine 57710 [runnable]:
fortio.org/fortio/fhttp.(*errgroup).Go.func1()
	/go/src/fortio.org/fortio/fhttp/httprunner.go:217
created by fortio.org/fortio/fhttp.(*errgroup).Go
	/go/src/fortio.org/fortio/fhttp/httprunner.go:217 +0x88

goroutine 57704 [runnable]:
fortio.org/fortio/fhttp.(*errgroup).Go.func1()
	/go/src/fortio.org/fortio/fhttp/httprunner.go:217
created by fortio.org/fortio/fhttp.(*errgroup).Go
	/go/src/fortio.org/fortio/fhttp/httprunner.go:217 +0x88

goroutine 57719 [runnable]:
fortio.org/fortio/fhttp.(*errgroup).Go.func1()
	/go/src/fortio.org/fortio/fhttp/httprunner.go:217
created by fortio.org/fortio/fhttp.(*errgroup).Go
	/go/src/fortio.org/fortio/fhttp/httprunner.go:217 +0x88

goroutine 57626 [select]:
net.(*Resolver).lookupIPAddr(0xef43a0, {0xb20348, 0xc0003fa000}, {0xa20010, 0x203000}, {0xc00023e000, 0x31})
	/usr/local/go/src/net/lookup.go:302 +0x5c7
net.(*Resolver).internetAddrList(0xb20348, {0xb20348, 0xc0003fa000}, {0xa20010, 0x3}, {0xc00023e000, 0x35})
	/usr/local/go/src/net/ipsock.go:288 +0x67a
net.(*Resolver).resolveAddrList(0xf25540, {0xb20348, 0xc0003fa000}, {0xa20570, 0x4}, {0xa20010, 0xc080655a05df8da0}, {0xc00023e000, 0x35}, {0x0, ...})
	/usr/local/go/src/net/dial.go:221 +0x41b
net.(*Dialer).DialContext(0xc00061d988, {0xb20348, 0xc0003fa000}, {0xa20010, 0x203000}, {0xc00023e000, 0x7f9650de7a26})
	/usr/local/go/src/net/dial.go:406 +0x448
fortio.org/fortio/fhttp.NewStdClient.func1({0xb20348, 0xc0003fa000}, {0xa20010, 0x60}, {0xc00023e000, 0x50cb73})
	/go/src/fortio.org/fortio/fhttp/http_client.go:438 +0x165
net/http.(*Transport).dial(0xc0003fa000, {0xb20348, 0xc0003fa000}, {0xa20010, 0x18}, {0xc00023e000, 0xc0004ac040})
	/usr/local/go/src/net/http/transport.go:1166 +0xda
net/http.(*Transport).dialConn(0xc0000ea000, {0xb20348, 0xc0003fa000}, {{}, 0x0, {0xc00050c180, 0x5}, {0xc00023e000, 0x35}, 0x0})
	/usr/local/go/src/net/http/transport.go:1604 +0x845
net/http.(*Transport).dialConnFor(0x695f26, 0xc000530000)
	/usr/local/go/src/net/http/transport.go:1446 +0xb0
created by net/http.(*Transport).queueForDial
	/usr/local/go/src/net/http/transport.go:1415 +0x3d7

goroutine 57699 [runnable]:
fortio.org/fortio/fhttp.(*errgroup).Go.func1()
	/go/src/fortio.org/fortio/fhttp/httprunner.go:217
created by fortio.org/fortio/fhttp.(*errgroup).Go
	/go/src/fortio.org/fortio/fhttp/httprunner.go:217 +0x88

goroutine 57686 [select]:
net/http.(*Transport).getConn(0xc0000ea500, 0xc0004b80c0, {{}, 0x0, {0xc00050c180, 0x5}, {0xc0001b82c0, 0x35}, 0x0})
	/usr/local/go/src/net/http/transport.go:1372 +0x5d2
net/http.(*Transport).roundTrip(0xc0000ea500, 0xc000224500)
	/usr/local/go/src/net/http/transport.go:581 +0x774
net/http.(*Transport).RoundTrip(0xc000224500, 0xb11480)
	/usr/local/go/src/net/http/roundtrip.go:18 +0x19
net/http.send(0xc000350300, {0xb11480, 0xc0000ea500}, {0xa0d6a0, 0x4bb501, 0xef5180})
	/usr/local/go/src/net/http/client.go:252 +0x5d8
net/http.(*Client).send(0xc0004cce10, 0xc000350300, {0x0, 0x0, 0xef5180})
	/usr/local/go/src/net/http/client.go:176 +0x9b
net/http.(*Client).do(0xc0004cce10, 0xc000350300)
	/usr/local/go/src/net/http/client.go:725 +0x908
net/http.(*Client).Do(...)
	/usr/local/go/src/net/http/client.go:593
fortio.org/fortio/fhttp.(*Client).Fetch(0xc00012e150)
	/go/src/fortio.org/fortio/fhttp/http_client.go:374 +0x7b
fortio.org/fortio/fhttp.RunHTTPTest.func1()
	/go/src/fortio.org/fortio/fhttp/httprunner.go:112 +0x73
fortio.org/fortio/fhttp.(*errgroup).Go.func1()
	/go/src/fortio.org/fortio/fhttp/httprunner.go:220 +0x63
created by fortio.org/fortio/fhttp.(*errgroup).Go
	/go/src/fortio.org/fortio/fhttp/httprunner.go:217 +0x88

goroutine 50577 [runnable]:
fortio.org/fortio/fhttp.NewStdClient(0xc000256278)
	/go/src/fortio.org/fortio/fhttp/http_client.go:431 +0xee
fortio.org/fortio/fhttp.NewClient(0xc000256278)
	/go/src/fortio.org/fortio/fhttp/http_client.go:413 +0x3f
fortio.org/fortio/fhttp.RunHTTPTest(0xc0002561c0)
	/go/src/fortio.org/fortio/fhttp/httprunner.go:104 +0x525
fortio.org/fortio/ui.Handler({0xb1e320, 0xc00025a1c0}, 0xc000224200)
	/go/src/fortio.org/fortio/ui/uihandler.go:319 +0x1965
net/http.HandlerFunc.ServeHTTP(0x100000000000000, {0xb1e320, 0xc00025a1c0}, 0x40)
	/usr/local/go/src/net/http/server.go:2047 +0x2f
net/http.(*ServeMux).ServeHTTP(0xb1e320, {0xb1e320, 0xc00025a1c0}, 0xc000224200)
	/usr/local/go/src/net/http/server.go:2425 +0x149
golang.org/x/net/http2/h2c.h2cHandler.ServeHTTP({{0xb11460, 0xc00021d000}, 0xc00021d040}, {0xb1e320, 0xc00025a1c0}, 0xc000224200)
	/go/pkg/mod/golang.org/x/net@v0.0.0-20220225172249-27dd8689420f/http2/h2c/h2c.go:104 +0x3e4
net/http.serverHandler.ServeHTTP({0xb1cf28}, {0xb1e320, 0xc00025a1c0}, 0xc000224200)
	/usr/local/go/src/net/http/server.go:2879 +0x43b
net/http.(*conn).serve(0xc00042a1e0, {0xb20380, 0xc0002ee0f0})
	/usr/local/go/src/net/http/server.go:1930 +0xb08
created by net/http.(*Server).Serve
	/usr/local/go/src/net/http/server.go:3034 +0x4e8

goroutine 57681 [IO wait]:
internal/poll.runtime_pollWait(0x7f9629f7de00, 0x72)
	/usr/local/go/src/runtime/netpoll.go:234 +0x89
internal/poll.(*pollDesc).wait(0xc000120080, 0xc0003799c1, 0x0)
	/usr/local/go/src/internal/poll/fd_poll_runtime.go:84 +0x32
internal/poll.(*pollDesc).waitRead(...)
	/usr/local/go/src/internal/poll/fd_poll_runtime.go:89
internal/poll.(*FD).Read(0xc000120080, {0xc0003799c1, 0x1, 0x1})
	/usr/local/go/src/internal/poll/fd_unix.go:167 +0x25a
net.(*netFD).Read(0xc000120080, {0xc0003799c1, 0x98a160, 0xc000190748})
	/usr/local/go/src/net/fd_posix.go:56 +0x29
net.(*conn).Read(0xc00063a218, {0xc0003799c1, 0xc000523f50, 0xc0003850e0})
	/usr/local/go/src/net/net.go:183 +0x45
net/http.(*connReader).backgroundRead(0xc0003799b0)
	/usr/local/go/src/net/http/server.go:672 +0x3f
created by net/http.(*connReader).startBackgroundRead
	/usr/local/go/src/net/http/server.go:668 +0xcf

goroutine 57692 [select]:
net/http.(*Transport).getConn(0xc0000eadc0, 0xc0003ba040, {{}, 0x0, {0xc00050c180, 0x5}, {0xc0000d4240, 0x35}, 0x0})
	/usr/local/go/src/net/http/transport.go:1372 +0x5d2
net/http.(*Transport).roundTrip(0xc0000eadc0, 0xc000198000)
	/usr/local/go/src/net/http/transport.go:581 +0x774
net/http.(*Transport).RoundTrip(0xc000198000, 0xb11480)
	/usr/local/go/src/net/http/roundtrip.go:18 +0x19
net/http.send(0xc000350900, {0xb11480, 0xc0000eadc0}, {0xa0d6a0, 0x4bb501, 0xef5180})
	/usr/local/go/src/net/http/client.go:252 +0x5d8
net/http.(*Client).send(0xc0004cd4d0, 0xc000350900, {0x0, 0x0, 0xef5180})
	/usr/local/go/src/net/http/client.go:176 +0x9b
net/http.(*Client).do(0xc0004cd4d0, 0xc000350900)
	/usr/local/go/src/net/http/client.go:725 +0x908
net/http.(*Client).Do(...)
	/usr/local/go/src/net/http/client.go:593
fortio.org/fortio/fhttp.(*Client).Fetch(0xc00012e3f0)
	/go/src/fortio.org/fortio/fhttp/http_client.go:374 +0x7b
fortio.org/fortio/fhttp.RunHTTPTest.func1()
	/go/src/fortio.org/fortio/fhttp/httprunner.go:112 +0x73
fortio.org/fortio/fhttp.(*errgroup).Go.func1()
	/go/src/fortio.org/fortio/fhttp/httprunner.go:220 +0x63
created by fortio.org/fortio/fhttp.(*errgroup).Go
	/go/src/fortio.org/fortio/fhttp/httprunner.go:217 +0x88

goroutine 57683 [select]:
net/http.(*Transport).getConn(0xc0000ea000, 0xc0002fa080, {{}, 0x0, {0xc00050c180, 0x5}, {0xc00023e000, 0x35}, 0x0})
	/usr/local/go/src/net/http/transport.go:1372 +0x5d2
net/http.(*Transport).roundTrip(0xc0000ea000, 0xc00052e000)
	/usr/local/go/src/net/http/transport.go:581 +0x774
net/http.(*Transport).RoundTrip(0xc00052e000, 0xb11480)
	/usr/local/go/src/net/http/roundtrip.go:18 +0x19
net/http.send(0xc000350000, {0xb11480, 0xc0000ea000}, {0xa0d6a0, 0x4bb501, 0xef5180})
	/usr/local/go/src/net/http/client.go:252 +0x5d8
net/http.(*Client).send(0xc0004ccab0, 0xc000350000, {0x50cb73, 0x59d629, 0xef5180})
	/usr/local/go/src/net/http/client.go:176 +0x9b
net/http.(*Client).do(0xc0004ccab0, 0xc000350000)
	/usr/local/go/src/net/http/client.go:725 +0x908
net/http.(*Client).Do(...)
	/usr/local/go/src/net/http/client.go:593
fortio.org/fortio/fhttp.(*Client).Fetch(0xc00012e000)
	/go/src/fortio.org/fortio/fhttp/http_client.go:374 +0x7b
fortio.org/fortio/fhttp.RunHTTPTest.func1()
	/go/src/fortio.org/fortio/fhttp/httprunner.go:112 +0x73
fortio.org/fortio/fhttp.(*errgroup).Go.func1()
	/go/src/fortio.org/fortio/fhttp/httprunner.go:220 +0x63
created by fortio.org/fortio/fhttp.(*errgroup).Go
	/go/src/fortio.org/fortio/fhttp/httprunner.go:217 +0x88

goroutine 56565 [select]:
net.(*Resolver).lookupIPAddr(0xef43a0, {0xb20348, 0xc0006ac000}, {0xa20010, 0x203000}, {0xc0000d4240, 0x31})
	/usr/local/go/src/net/lookup.go:302 +0x5c7
net.(*Resolver).internetAddrList(0xb20348, {0xb20348, 0xc0006ac000}, {0xa20010, 0x3}, {0xc0000d4240, 0x35})
	/usr/local/go/src/net/ipsock.go:288 +0x67a
net.(*Resolver).resolveAddrList(0xf25540, {0xb20348, 0xc0006ac000}, {0xa20570, 0x4}, {0xa20010, 0xc080655a05e0a16d}, {0xc0000d4240, 0x35}, {0x0, ...})
	/usr/local/go/src/net/dial.go:221 +0x41b
net.(*Dialer).DialContext(0xc0004fd988, {0xb20348, 0xc0006ac000}, {0xa20010, 0x203000}, {0xc0000d4240, 0x7f9650de8d26})
	/usr/local/go/src/net/dial.go:406 +0x448
fortio.org/fortio/fhttp.NewStdClient.func1({0xb20348, 0xc0006ac000}, {0xa20010, 0x60}, {0xc0000d4240, 0x50cb73})
	/go/src/fortio.org/fortio/fhttp/http_client.go:438 +0x165
net/http.(*Transport).dial(0xc0006ac000, {0xb20348, 0xc0006ac000}, {0xa20010, 0x0}, {0xc0000d4240, 0x0})
	/usr/local/go/src/net/http/transport.go:1166 +0xda
net/http.(*Transport).dialConn(0xc0000eadc0, {0xb20348, 0xc0006ac000}, {{}, 0x0, {0xc00050c180, 0x5}, {0xc0000d4240, 0x35}, 0x0})
	/usr/local/go/src/net/http/transport.go:1604 +0x845
net/http.(*Transport).dialConnFor(0x6b3c86, 0xc00019a000)
	/usr/local/go/src/net/http/transport.go:1446 +0xb0
created by net/http.(*Transport).queueForDial
	/usr/local/go/src/net/http/transport.go:1415 +0x3d7

goroutine 57696 [runnable]:
fortio.org/fortio/fhttp.(*errgroup).Go.func1()
	/go/src/fortio.org/fortio/fhttp/httprunner.go:217
created by fortio.org/fortio/fhttp.(*errgroup).Go
	/go/src/fortio.org/fortio/fhttp/httprunner.go:217 +0x88

goroutine 57720 [runnable]:
fortio.org/fortio/fhttp.(*errgroup).Go.func1()
	/go/src/fortio.org/fortio/fhttp/httprunner.go:217
created by fortio.org/fortio/fhttp.(*errgroup).Go
	/go/src/fortio.org/fortio/fhttp/httprunner.go:217 +0x88

goroutine 56566 [select]:
net.(*Resolver).lookupIPAddr(0xef43a0, {0xb20348, 0xc0006ac420}, {0xa20010, 0x203000}, {0xc0000d4440, 0x31})
	/usr/local/go/src/net/lookup.go:302 +0x5c7
net.(*Resolver).internetAddrList(0xb20348, {0xb20348, 0xc0006ac420}, {0xa20010, 0x3}, {0xc0000d4440, 0x35})
	/usr/local/go/src/net/ipsock.go:288 +0x67a
net.(*Resolver).resolveAddrList(0xf25540, {0xb20348, 0xc0006ac420}, {0xa20570, 0x4}, {0xa20010, 0xc080655a05e31f15}, {0xc0000d4440, 0x35}, {0x0, ...})
	/usr/local/go/src/net/dial.go:221 +0x41b
net.(*Dialer).DialContext(0xc000321988, {0xb20348, 0xc0006ac420}, {0xa20010, 0x203000}, {0xc0000d4440, 0x7f9650de8d28})
	/usr/local/go/src/net/dial.go:406 +0x448
fortio.org/fortio/fhttp.NewStdClient.func1({0xb20348, 0xc0006ac420}, {0xa20010, 0x60}, {0xc0000d4440, 0x50cb73})
	/go/src/fortio.org/fortio/fhttp/http_client.go:438 +0x165
net/http.(*Transport).dial(0xc0006ac420, {0xb20348, 0xc0006ac420}, {0xa20010, 0x0}, {0xc0000d4440, 0x0})
	/usr/local/go/src/net/http/transport.go:1166 +0xda
net/http.(*Transport).dialConn(0xc0000eaa00, {0xb20348, 0xc0006ac420}, {{}, 0x0, {0xc00050c180, 0x5}, {0xc0000d4440, 0x35}, 0x0})
	/usr/local/go/src/net/http/transport.go:1604 +0x845
net/http.(*Transport).dialConnFor(0x6b3c26, 0xc00019a0b0)
	/usr/local/go/src/net/http/transport.go:1446 +0xb0
created by net/http.(*Transport).queueForDial
	/usr/local/go/src/net/http/transport.go:1415 +0x3d7

goroutine 57712 [runnable]:
fortio.org/fortio/fhttp.(*errgroup).Go.func1()
	/go/src/fortio.org/fortio/fhttp/httprunner.go:217
created by fortio.org/fortio/fhttp.(*errgroup).Go
	/go/src/fortio.org/fortio/fhttp/httprunner.go:217 +0x88

goroutine 57691 [runnable]:
fortio.org/fortio/fhttp.(*errgroup).Go.func1()
	/go/src/fortio.org/fortio/fhttp/httprunner.go:217
created by fortio.org/fortio/fhttp.(*errgroup).Go
	/go/src/fortio.org/fortio/fhttp/httprunner.go:217 +0x88

goroutine 57703 [select]:
net/http.(*Transport).getConn(0xc000168000, 0xc0002fa180, {{}, 0x0, {0xc00050c180, 0x5}, {0xc00023e080, 0x35}, 0x0})
	/usr/local/go/src/net/http/transport.go:1372 +0x5d2
net/http.(*Transport).roundTrip(0xc000168000, 0xc00052e200)
	/usr/local/go/src/net/http/transport.go:581 +0x774
net/http.(*Transport).RoundTrip(0xc00052e200, 0xb11480)
	/usr/local/go/src/net/http/roundtrip.go:18 +0x19
net/http.send(0xc000351400, {0xb11480, 0xc000168000}, {0xa0d6a0, 0x4bb501, 0xef5180})
	/usr/local/go/src/net/http/client.go:252 +0x5d8
net/http.(*Client).send(0xc00014a720, 0xc000351400, {0x50cb73, 0x118, 0xef5180})
	/usr/local/go/src/net/http/client.go:176 +0x9b
net/http.(*Client).do(0xc00014a720, 0xc000351400)
	/usr/local/go/src/net/http/client.go:725 +0x908
net/http.(*Client).Do(...)
	/usr/local/go/src/net/http/client.go:593
fortio.org/fortio/fhttp.(*Client).Fetch(0xc00012e9a0)
	/go/src/fortio.org/fortio/fhttp/http_client.go:374 +0x7b
fortio.org/fortio/fhttp.RunHTTPTest.func1()
	/go/src/fortio.org/fortio/fhttp/httprunner.go:112 +0x73
fortio.org/fortio/fhttp.(*errgroup).Go.func1()
	/go/src/fortio.org/fortio/fhttp/httprunner.go:220 +0x63
created by fortio.org/fortio/fhttp.(*errgroup).Go
	/go/src/fortio.org/fortio/fhttp/httprunner.go:217 +0x88

goroutine 57708 [runnable]:
fortio.org/fortio/fhttp.(*errgroup).Go.func1()
	/go/src/fortio.org/fortio/fhttp/httprunner.go:217
created by fortio.org/fortio/fhttp.(*errgroup).Go
	/go/src/fortio.org/fortio/fhttp/httprunner.go:217 +0x88

goroutine 57688 [select]:
net/http.(*Transport).getConn(0xc0000ea780, 0xc000188040, {{}, 0x0, {0xc00050c180, 0x5}, {0xc0001de000, 0x35}, 0x0})
	/usr/local/go/src/net/http/transport.go:1372 +0x5d2
net/http.(*Transport).roundTrip(0xc0000ea780, 0xc0001a4000)
	/usr/local/go/src/net/http/transport.go:581 +0x774
net/http.(*Transport).RoundTrip(0xc0001a4000, 0xb11480)
	/usr/local/go/src/net/http/roundtrip.go:18 +0x19
net/http.send(0xc000350500, {0xb11480, 0xc0000ea780}, {0xa0d6a0, 0x4bb501, 0xef5180})
	/usr/local/go/src/net/http/client.go:252 +0x5d8
net/http.(*Client).send(0xc0004cd050, 0xc000350500, {0x666c616865422d6e, 0x31225b3a22664f2d, 0xef5180})
	/usr/local/go/src/net/http/client.go:176 +0x9b
net/http.(*Client).do(0xc0004cd050, 0xc000350500)
	/usr/local/go/src/net/http/client.go:725 +0x908
net/http.(*Client).Do(...)
	/usr/local/go/src/net/http/client.go:593
fortio.org/fortio/fhttp.(*Client).Fetch(0xc00012e230)
	/go/src/fortio.org/fortio/fhttp/http_client.go:374 +0x7b
fortio.org/fortio/fhttp.RunHTTPTest.func1()
	/go/src/fortio.org/fortio/fhttp/httprunner.go:112 +0x73
fortio.org/fortio/fhttp.(*errgroup).Go.func1()
	/go/src/fortio.org/fortio/fhttp/httprunner.go:220 +0x63
created by fortio.org/fortio/fhttp.(*errgroup).Go
	/go/src/fortio.org/fortio/fhttp/httprunner.go:217 +0x88

goroutine 57684 [select]:
net/http.(*Transport).getConn(0xc0000ea280, 0xc000522040, {{}, 0x0, {0xc00050c180, 0x5}, {0xc000028080, 0x35}, 0x0})
	/usr/local/go/src/net/http/transport.go:1372 +0x5d2
net/http.(*Transport).roundTrip(0xc0000ea280, 0xc0006d0000)
	/usr/local/go/src/net/http/transport.go:581 +0x774
net/http.(*Transport).RoundTrip(0xc0006d0000, 0xb11480)
	/usr/local/go/src/net/http/roundtrip.go:18 +0x19
net/http.send(0xc000350100, {0xb11480, 0xc0000ea280}, {0xa0d6a0, 0x4bb501, 0xef5180})
	/usr/local/go/src/net/http/client.go:252 +0x5d8
net/http.(*Client).send(0xc0004ccbd0, 0xc000350100, {0xc0002f7a50, 0x46361b, 0xef5180})
	/usr/local/go/src/net/http/client.go:176 +0x9b
net/http.(*Client).do(0xc0004ccbd0, 0xc000350100)
	/usr/local/go/src/net/http/client.go:725 +0x908
net/http.(*Client).Do(...)
	/usr/local/go/src/net/http/client.go:593
fortio.org/fortio/fhttp.(*Client).Fetch(0xc00012e070)
	/go/src/fortio.org/fortio/fhttp/http_client.go:374 +0x7b
fortio.org/fortio/fhttp.RunHTTPTest.func1()
	/go/src/fortio.org/fortio/fhttp/httprunner.go:112 +0x73
fortio.org/fortio/fhttp.(*errgroup).Go.func1()
	/go/src/fortio.org/fortio/fhttp/httprunner.go:220 +0x63
created by fortio.org/fortio/fhttp.(*errgroup).Go
	/go/src/fortio.org/fortio/fhttp/httprunner.go:217 +0x88

goroutine 57718 [runnable]:
fortio.org/fortio/fhttp.(*errgroup).Go.func1()
	/go/src/fortio.org/fortio/fhttp/httprunner.go:217
created by fortio.org/fortio/fhttp.(*errgroup).Go
	/go/src/fortio.org/fortio/fhttp/httprunner.go:217 +0x88

goroutine 57682 [select]:
fortio.org/fortio/periodic.(*RunnerOptions).Normalize.func1()
	/go/src/fortio.org/fortio/periodic/periodic.go:251 +0x2e6
created by fortio.org/fortio/periodic.(*RunnerOptions).Normalize
	/go/src/fortio.org/fortio/periodic/periodic.go:239 +0x2bd

goroutine 57745 [runnable]:
net/http.(*Transport).queueForDial·dwrap·112()
	/usr/local/go/src/net/http/transport.go:1415
runtime.goexit()
	/usr/local/go/src/runtime/asm_amd64.s:1581 +0x1
created by net/http.(*Transport).queueForDial
	/usr/local/go/src/net/http/transport.go:1415 +0x3d7

goroutine 57698 [runnable]:
fortio.org/fortio/fhttp.(*errgroup).Go.func1()
	/go/src/fortio.org/fortio/fhttp/httprunner.go:217
created by fortio.org/fortio/fhttp.(*errgroup).Go
	/go/src/fortio.org/fortio/fhttp/httprunner.go:217 +0x88

goroutine 57687 [runnable]:
time.startTimer(0xc000738008)
	/usr/local/go/src/runtime/time.go:208 +0x2d
time.AfterFunc(0xb20310, 0xc00009e270)
	/usr/local/go/src/time/sleep.go:175 +0x88
context.WithDeadline({0xb20310, 0xc0000bc020}, {0xef5180, 0xb20310, 0xef5180})
	/usr/local/go/src/context/context.go:455 +0x298
net/http.setRequestCancel(0xc000328000, {0xb11480, 0xc0000ea640}, {0x0, 0xfb6800, 0xef5180})
	/usr/local/go/src/net/http/client.go:359 +0x4ee
net/http.send(0xc000350400, {0xb11480, 0xc0000ea640}, {0xa0d6a0, 0x4bb501, 0xef5180})
	/usr/local/go/src/net/http/client.go:250 +0x5a6
net/http.(*Client).send(0xc0004ccf30, 0xc000350400, {0x0, 0x0, 0xef5180})
	/usr/local/go/src/net/http/client.go:176 +0x9b
net/http.(*Client).do(0xc0004ccf30, 0xc000350400)
	/usr/local/go/src/net/http/client.go:725 +0x908
net/http.(*Client).Do(...)
	/usr/local/go/src/net/http/client.go:593
fortio.org/fortio/fhttp.(*Client).Fetch(0xc00012e1c0)
	/go/src/fortio.org/fortio/fhttp/http_client.go:374 +0x7b
fortio.org/fortio/fhttp.RunHTTPTest.func1()
	/go/src/fortio.org/fortio/fhttp/httprunner.go:112 +0x73
fortio.org/fortio/fhttp.(*errgroup).Go.func1()
	/go/src/fortio.org/fortio/fhttp/httprunner.go:220 +0x63
created by fortio.org/fortio/fhttp.(*errgroup).Go
	/go/src/fortio.org/fortio/fhttp/httprunner.go:217 +0x88

goroutine 57716 [runnable]:
fortio.org/fortio/fhttp.(*errgroup).Go.func1()
	/go/src/fortio.org/fortio/fhttp/httprunner.go:217
created by fortio.org/fortio/fhttp.(*errgroup).Go
	/go/src/fortio.org/fortio/fhttp/httprunner.go:217 +0x88

goroutine 57711 [runnable]:
fortio.org/fortio/fhttp.(*errgroup).Go.func1()
	/go/src/fortio.org/fortio/fhttp/httprunner.go:217
created by fortio.org/fortio/fhttp.(*errgroup).Go
	/go/src/fortio.org/fortio/fhttp/httprunner.go:217 +0x88

goroutine 57694 [runnable]:
fortio.org/fortio/fhttp.(*errgroup).Go.func1()
	/go/src/fortio.org/fortio/fhttp/httprunner.go:217
created by fortio.org/fortio/fhttp.(*errgroup).Go
	/go/src/fortio.org/fortio/fhttp/httprunner.go:217 +0x88

goroutine 57714 [runnable]:
fortio.org/fortio/fhttp.(*errgroup).Go.func1()
	/go/src/fortio.org/fortio/fhttp/httprunner.go:217
created by fortio.org/fortio/fhttp.(*errgroup).Go
	/go/src/fortio.org/fortio/fhttp/httprunner.go:217 +0x88

goroutine 57700 [runnable]:
fortio.org/fortio/fhttp.(*errgroup).Go.func1()
	/go/src/fortio.org/fortio/fhttp/httprunner.go:217
created by fortio.org/fortio/fhttp.(*errgroup).Go
	/go/src/fortio.org/fortio/fhttp/httprunner.go:217 +0x88

goroutine 57664 [select]:
net.(*Resolver).lookupIPAddr(0xef43a0, {0xb20348, 0xc0006281e0}, {0xa20010, 0x203000}, {0xc0001b82c0, 0x31})
	/usr/local/go/src/net/lookup.go:302 +0x5c7
net.(*Resolver).internetAddrList(0xb20348, {0xb20348, 0xc0006281e0}, {0xa20010, 0x3}, {0xc0001b82c0, 0x35})
	/usr/local/go/src/net/ipsock.go:288 +0x67a
net.(*Resolver).resolveAddrList(0xf25540, {0xb20348, 0xc0006281e0}, {0xa20570, 0x4}, {0xa20010, 0xc080655a05e06118}, {0xc0001b82c0, 0x35}, {0x0, ...})
	/usr/local/go/src/net/dial.go:221 +0x41b
net.(*Dialer).DialContext(0xc000469988, {0xb20348, 0xc0006281e0}, {0xa20010, 0x203000}, {0xc0001b82c0, 0x7f9650de7126})
	/usr/local/go/src/net/dial.go:406 +0x448
fortio.org/fortio/fhttp.NewStdClient.func1({0xb20348, 0xc0006281e0}, {0xa20010, 0x60}, {0xc0001b82c0, 0x50cb73})
	/go/src/fortio.org/fortio/fhttp/http_client.go:438 +0x165
net/http.(*Transport).dial(0xc0006281e0, {0xb20348, 0xc0006281e0}, {0xa20010, 0x0}, {0xc0001b82c0, 0x0})
	/usr/local/go/src/net/http/transport.go:1166 +0xda
net/http.(*Transport).dialConn(0xc0000ea500, {0xb20348, 0xc0006281e0}, {{}, 0x0, {0xc00050c180, 0x5}, {0xc0001b82c0, 0x35}, 0x0})
	/usr/local/go/src/net/http/transport.go:1604 +0x845
net/http.(*Transport).dialConnFor(0x695f26, 0xc000258160)
	/usr/local/go/src/net/http/transport.go:1446 +0xb0
created by net/http.(*Transport).queueForDial
	/usr/local/go/src/net/http/transport.go:1415 +0x3d7

goroutine 57695 [runnable]:
fortio.org/fortio/fhttp.(*errgroup).Go.func1()
	/go/src/fortio.org/fortio/fhttp/httprunner.go:217
created by fortio.org/fortio/fhttp.(*errgroup).Go
	/go/src/fortio.org/fortio/fhttp/httprunner.go:217 +0x88

goroutine 56970 [select]:
net.(*Resolver).lookupIPAddr(0xef43a0, {0xb20348, 0xc0006e2000}, {0xa20010, 0x203000}, {0xc000028080, 0x31})
	/usr/local/go/src/net/lookup.go:302 +0x5c7
net.(*Resolver).internetAddrList(0xb20348, {0xb20348, 0xc0006e2000}, {0xa20010, 0x3}, {0xc000028080, 0x35})
	/usr/local/go/src/net/ipsock.go:288 +0x67a
net.(*Resolver).resolveAddrList(0xf25540, {0xb20348, 0xc0006e2000}, {0xa20570, 0x4}, {0xa20010, 0x400}, {0xc000028080, 0x35}, {0x0, ...})
	/usr/local/go/src/net/dial.go:221 +0x41b
net.(*Dialer).DialContext(0xc00061f988, {0xb20348, 0xc0006e2000}, {0xa20010, 0x203000}, {0xc000028080, 0x7f9650de9126})
	/usr/local/go/src/net/dial.go:406 +0x448
fortio.org/fortio/fhttp.NewStdClient.func1({0xb20348, 0xc0006e2000}, {0xa20010, 0x60}, {0xc000028080, 0x50cb73})
	/go/src/fortio.org/fortio/fhttp/http_client.go:438 +0x165
net/http.(*Transport).dial(0xc0006e2000, {0xb20348, 0xc0006e2000}, {0xa20010, 0xf}, {0xc000028080, 0x4c9185})
	/usr/local/go/src/net/http/transport.go:1166 +0xda
net/http.(*Transport).dialConn(0xc0000ea280, {0xb20348, 0xc0006e2000}, {{}, 0x0, {0xc00050c180, 0x5}, {0xc000028080, 0x35}, 0x0})
	/usr/local/go/src/net/http/transport.go:1604 +0x845
net/http.(*Transport).dialConnFor(0x6b3c26, 0xc0006d2000)
	/usr/local/go/src/net/http/transport.go:1446 +0xb0
created by net/http.(*Transport).queueForDial
	/usr/local/go/src/net/http/transport.go:1415 +0x3d7

goroutine 57713 [runnable]:
fortio.org/fortio/fhttp.(*errgroup).Go.func1()
	/go/src/fortio.org/fortio/fhttp/httprunner.go:217
created by fortio.org/fortio/fhttp.(*errgroup).Go
	/go/src/fortio.org/fortio/fhttp/httprunner.go:217 +0x88

goroutine 57717 [runnable]:
fortio.org/fortio/fhttp.(*errgroup).Go.func1()
	/go/src/fortio.org/fortio/fhttp/httprunner.go:217
created by fortio.org/fortio/fhttp.(*errgroup).Go
	/go/src/fortio.org/fortio/fhttp/httprunner.go:217 +0x88

goroutine 57705 [runnable]:
fortio.org/fortio/fhttp.(*errgroup).Go.func1()
	/go/src/fortio.org/fortio/fhttp/httprunner.go:217
created by fortio.org/fortio/fhttp.(*errgroup).Go
	/go/src/fortio.org/fortio/fhttp/httprunner.go:217 +0x88

goroutine 57693 [runnable]:
fortio.org/fortio/fhttp.(*errgroup).Go.func1()
	/go/src/fortio.org/fortio/fhttp/httprunner.go:217
created by fortio.org/fortio/fhttp.(*errgroup).Go
	/go/src/fortio.org/fortio/fhttp/httprunner.go:217 +0x88

goroutine 57715 [runnable]:
fortio.org/fortio/fhttp.(*errgroup).Go.func1()
	/go/src/fortio.org/fortio/fhttp/httprunner.go:217
created by fortio.org/fortio/fhttp.(*errgroup).Go
	/go/src/fortio.org/fortio/fhttp/httprunner.go:217 +0x88
❯
```
<Container Restart>

***What I Expected to Happen***
Test to complete, just like it does when there is no payload specified.

***Version***
Φορτίο version 1.21.0 2022-02-27 23:35 4b1eec7b82bc0a626af9c253a270673fa3721751 go1.17.7

***Notes***
Works find on 1.17.1



Pull request:
fix the warm up race/crash and add `-sequential-warmup` option
- [x] reproduce issue #514 with a test
- [x] actual fix from #515 (thanks @howardjohn )
- [x] make the parallel vs sequential warmup configurable (`-sequential-warmup` flag)

Fixes #514 

Patch:
diff --git a/.circleci/config.yml b/.circleci/config.yml
index 21edd4c..86551d7 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -7,7 +7,7 @@ version: 2
 defaultEnv: &defaultEnv
     docker:
       # specify the version
-      - image: docker.io/fortio/fortio.build:v37
+      - image: docker.io/fortio/fortio.build:v38
     working_directory: /go/src/fortio.org/fortio
 
 jobs:
diff --git a/Dockerfile b/Dockerfile
index 9302ab7..d874902 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,5 +1,5 @@
 # Build the binaries in larger image
-FROM docker.io/fortio/fortio.build:v37 as build
+FROM docker.io/fortio/fortio.build:v38 as build
 WORKDIR /go/src/fortio.org
 COPY . fortio
 # We moved a lot of the logic into the Makefile so it can be reused in brew
diff --git a/Dockerfile.build b/Dockerfile.build
index efc282f..8c2fd82 100644
--- a/Dockerfile.build
+++ b/Dockerfile.build
@@ -8,7 +8,7 @@ RUN apt-get -y update && \
 # Install FPM
 RUN gem install --no-document fpm
 # From fortio 1.4 onward we dropped go 1.8 compatibility
-RUN curl -f https://dl.google.com/go/go1.17.7.linux-amd64.tar.gz | tar xfz - -C /usr/local
+RUN curl -f https://dl.google.com/go/go1.17.8.linux-amd64.tar.gz | tar xfz - -C /usr/local
 ENV GOPATH /go
 RUN mkdir -p $GOPATH/bin
 ENV PATH /usr/local/go/bin:$PATH:$GOPATH/bin
diff --git a/Dockerfile.echosrv b/Dockerfile.echosrv
index 5340f94..a3b6473 100644
--- a/Dockerfile.echosrv
+++ b/Dockerfile.echosrv
@@ -1,5 +1,5 @@
 # Build the binaries in larger image
-FROM docker.io/fortio/fortio.build:v37 as build
+FROM docker.io/fortio/fortio.build:v38 as build
 WORKDIR /go/src/fortio.org
 COPY . fortio
 RUN make -C fortio official-build-version BUILD_DIR=/build OFFICIAL_TARGET=fortio.org/fortio/echosrv OFFICIAL_BIN=../echosrv.bin
diff --git a/Dockerfile.fcurl b/Dockerfile.fcurl
index fd4397a..6285ec9 100644
--- a/Dockerfile.fcurl
+++ b/Dockerfile.fcurl
@@ -1,5 +1,5 @@
 # Build the binaries in larger image
-FROM docker.io/fortio/fortio.build:v37 as build
+FROM docker.io/fortio/fortio.build:v38 as build
 WORKDIR /go/src/fortio.org
 COPY . fortio
 # fcurl should not need vendor/no dependencies
diff --git a/Makefile b/Makefile
index c084cb5..c771fe7 100755
--- a/Makefile
+++ b/Makefile
@@ -7,7 +7,7 @@
 IMAGES=echosrv fcurl # plus the combo image / Dockerfile without ext.
 
 DOCKER_PREFIX := docker.io/fortio/fortio
-BUILD_IMAGE_TAG := v37
+BUILD_IMAGE_TAG := v38
 BUILD_IMAGE := $(DOCKER_PREFIX).build:$(BUILD_IMAGE_TAG)
 
 TAG:=$(USER)$(shell date +%y%m%d_%H%M%S)
diff --git a/README.md b/README.md
index 9767ab9..38dc2e7 100644
--- a/README.md
+++ b/README.md
@@ -46,13 +46,13 @@ docker run fortio/fortio load http://www.google.com/ # For a test run
 Or download one of the binary distributions, from the [releases](https://github.com/fortio/fortio/releases) assets page or for instance:
 
 ```shell
-curl -L https://github.com/fortio/fortio/releases/download/v1.21.0/fortio-linux_x64-1.21.0.tgz \
+curl -L https://github.com/fortio/fortio/releases/download/v1.21.1/fortio-linux_x64-1.21.1.tgz \
  | sudo tar -C / -xvzpf -
 # or the debian package
-wget https://github.com/fortio/fortio/releases/download/v1.21.0/fortio_1.21.0_amd64.deb
-dpkg -i fortio_1.21.0_amd64.deb
+wget https://github.com/fortio/fortio/releases/download/v1.21.1/fortio_1.21.1_amd64.deb
+dpkg -i fortio_1.21.1_amd64.deb
 # or the rpm
-rpm -i https://github.com/fortio/fortio/releases/download/v1.21.0/fortio-1.21.0-1.x86_64.rpm
+rpm -i https://github.com/fortio/fortio/releases/download/v1.21.1/fortio-1.21.1-1.x86_64.rpm
 ```
 
 On a MacOS you can also install Fortio using [Homebrew](https://brew.sh/):
@@ -61,7 +61,7 @@ On a MacOS you can also install Fortio using [Homebrew](https://brew.sh/):
 brew install fortio
 ```
 
-On Windows, download https://github.com/fortio/fortio/releases/download/v1.21.0/fortio_win_1.21.0.zip and extract `fortio.exe` to any location, then using the Windows Command Prompt:
+On Windows, download https://github.com/fortio/fortio/releases/download/v1.21.1/fortio_win_1.21.1.zip and extract `fortio.exe` to any location, then using the Windows Command Prompt:
 ```
 fortio.exe server
 ```
@@ -104,7 +104,7 @@ Full list of command line flags (`fortio help`):
 <details>
 <!-- use release/updateFlags.sh to update this section -->
 <pre>
-Φορτίο 1.21.0 usage:
+Φορτίο 1.21.1 usage:
 where command is one of: load (load testing), server (starts ui, http-echo,
  redirect, proxies, tcp-echo and grpc ping servers), tcp-echo (only the tcp-echo
  server), report (report only UI server), redirect (only the redirect server),
@@ -266,6 +266,9 @@ disable the feature. (default "8081")
 server mode
   -s int
         Number of streams per grpc connection (default 1)
+  -sequential-warmup
+        http(s) runner warmup done in parallel instead of sequentially. When
+set, restores pre 1.21 behavior
   -static-dir path
         Deprecated/unused path.
   -stdclient
diff --git a/bincommon/commonflags.go b/bincommon/commonflags.go
index 415f262..2df6805 100644
--- a/bincommon/commonflags.go
+++ b/bincommon/commonflags.go
@@ -101,7 +101,9 @@ var (
 	// RunIDFlag is optional RunID to be present in json results (and default json result filename if not 0).
 	RunIDFlag = flag.Int64("runid", 0, "Optional RunID to add to json result and auto save filename, to match server mode")
 	// HelpFlag is true if help/usage is being requested by the user.
-	HelpFlag = flag.Bool("h", false, "Print usage/help on stdout")
+	HelpFlag   = flag.Bool("h", false, "Print usage/help on stdout")
+	warmupFlag = flag.Bool("sequential-warmup", false,
+		"http(s) runner warmup done in parallel instead of sequentially. When set, restores pre 1.21 behavior")
 )
 
 // SharedMain is the common part of main from fortio_main and fcurl.
@@ -186,5 +188,6 @@ func SharedHTTPOptions() *fhttp.HTTPOptions {
 	httpOpts.Cert = *CertFlag
 	httpOpts.Key = *KeyFlag
 	httpOpts.LogErrors = *LogErrorsFlag
+	httpOpts.SequentialWarmup = *warmupFlag
 	return &httpOpts
 }
diff --git a/fhttp/http_client.go b/fhttp/http_client.go
index 03dac71..d4455b4 100644
--- a/fhttp/http_client.go
+++ b/fhttp/http_client.go
@@ -192,6 +192,7 @@ type HTTPOptions struct {
 	UnixDomainSocket string // Path of unix domain socket to use instead of host:port from URL
 	LogErrors        bool   // whether to log non 2xx code as they occur or not
 	ID               int    // id to use for logging (thread id when used as a runner)
+	SequentialWarmup bool   // whether to do http(s) runs warmup sequentially or in parallel (new default is //)
 }
 
 // ResetHeaders resets all the headers, including the User-Agent: one (and the Host: logical special header).
diff --git a/fhttp/httprunner.go b/fhttp/httprunner.go
index 064d340..f3873b4 100644
--- a/fhttp/httprunner.go
+++ b/fhttp/httprunner.go
@@ -40,9 +40,9 @@ type HTTPRunnerResults struct {
 	sizes       *stats.Histogram
 	headerSizes *stats.Histogram
 	// exported result
+	HTTPOptions
 	Sizes       *stats.HistogramData
 	HeaderSizes *stats.HistogramData
-	URL         string
 	SocketCount int
 	// http code to abort the run on (-1 for connection or other socket error)
 	AbortOn int
@@ -77,24 +77,30 @@ type HTTPRunnerOptions struct {
 }
 
 // RunHTTPTest runs an http test and returns the aggregated stats.
+// nolint: funlen, gocognit
 func RunHTTPTest(o *HTTPRunnerOptions) (*HTTPRunnerResults, error) {
 	o.RunType = "HTTP"
-	log.Infof("Starting http test for %s with %d threads at %.1f qps", o.URL, o.NumThreads, o.QPS)
+	warmupMode := "parallel"
+	if o.SequentialWarmup {
+		warmupMode = "sequential"
+	}
+	log.Infof("Starting http test for %s with %d threads at %.1f qps and %s warmup", o.URL, o.NumThreads, o.QPS, warmupMode)
 	r := periodic.NewPeriodicRunner(&o.RunnerOptions)
 	defer r.Options().Abort()
 	numThreads := r.Options().NumThreads
 	o.HTTPOptions.Init(o.URL)
 	out := r.Options().Out // Important as the default value is set from nil to stdout inside NewPeriodicRunner
 	total := HTTPRunnerResults{
+		HTTPOptions: o.HTTPOptions,
 		RetCodes:    make(map[int]int64),
 		sizes:       stats.NewHistogram(0, 100),
 		headerSizes: stats.NewHistogram(0, 5),
-		URL:         o.URL,
 		AbortOn:     o.AbortOn,
 		aborter:     r.Options().Stop,
 	}
 	httpstate := make([]HTTPRunnerResults, numThreads)
-	warmup := errgroup{}
+	// First build all the clients sequentially. This ensures we do not have data races when
+	// constructing requests.
 	for i := 0; i < numThreads; i++ {
 		r.Options().Runners[i] = &httpstate[i]
 		// Temp mutate the option so each client gets a logging id
@@ -106,7 +112,25 @@ func RunHTTPTest(o *HTTPRunnerOptions) (*HTTPRunnerResults, error) {
 		if err != nil {
 			return nil, err
 		}
-		if o.Exactly <= 0 {
+		if o.SequentialWarmup && o.Exactly <= 0 {
+			code, data, headerSize := httpstate[i].client.Fetch()
+			if !o.AllowInitialErrors && !codeIsOK(code) {
+				return nil, fmt.Errorf("error %d for %s: %q", code, o.URL, string(data))
+			}
+			if i == 0 && log.LogVerbose() {
+				log.LogVf("first hit of url %s: status %03d, headers %d, total %d\n%s\n", o.URL, code, headerSize, len(data), data)
+			}
+		}
+		// Setup the stats for each 'thread'
+		httpstate[i].sizes = total.sizes.Clone()
+		httpstate[i].headerSizes = total.headerSizes.Clone()
+		httpstate[i].RetCodes = make(map[int]int64)
+		httpstate[i].AbortOn = total.AbortOn
+		httpstate[i].aborter = total.aborter
+	}
+	if o.Exactly <= 0 && !o.SequentialWarmup {
+		warmup := errgroup{}
+		for i := 0; i < numThreads; i++ {
 			i := i
 			warmup.Go(func() error {
 				code, data, headerSize := httpstate[i].client.Fetch()
@@ -119,15 +143,9 @@ func RunHTTPTest(o *HTTPRunnerOptions) (*HTTPRunnerResults, error) {
 				return nil
 			})
 		}
-		// Setup the stats for each 'thread'
-		httpstate[i].sizes = total.sizes.Clone()
-		httpstate[i].headerSizes = total.headerSizes.Clone()
-		httpstate[i].RetCodes = make(map[int]int64)
-		httpstate[i].AbortOn = total.AbortOn
-		httpstate[i].aborter = total.aborter
-	}
-	if err := warmup.Wait(); err != nil {
-		return nil, err
+		if err := warmup.Wait(); err != nil {
+			return nil, err
+		}
 	}
 	// TODO avoid copy pasta with grpcrunner
 	if o.Profiler != "" {
diff --git a/release/Dockerfile.in b/release/Dockerfile.in
index 301f12a..1e2e20c 100644
--- a/release/Dockerfile.in
+++ b/release/Dockerfile.in
@@ -1,5 +1,5 @@
 # Concatenated after ../Dockerfile to create the tgz
-FROM docker.io/fortio/fortio.build:v37 as stage
+FROM docker.io/fortio/fortio.build:v38 as stage
 WORKDIR /stage
 COPY --from=release /usr/bin/fortio usr/bin/fortio
 #COPY --from=release /usr/share/fortio usr/share/fortio
diff --git a/ui/restHandler.go b/ui/restHandler.go
index 6add385..2faa6d8 100644
--- a/ui/restHandler.go
+++ b/ui/restHandler.go
@@ -136,6 +136,7 @@ func RESTRunHandler(w http.ResponseWriter, r *http.Request) { // nolint: funlen
 	jitter := (FormValue(r, jd, "jitter") == "on")
 	uniform := (FormValue(r, jd, "uniform") == "on")
 	stdClient := (FormValue(r, jd, "stdclient") == "on")
+	sequentialWarmup := (r.FormValue("sequential-warmup") == "on")
 	httpsInsecure := (FormValue(r, jd, "https-insecure") == "on")
 	resolve := FormValue(r, jd, "resolve")
 	timeoutStr := strings.TrimSpace(FormValue(r, jd, "timeout"))
@@ -185,6 +186,7 @@ func RESTRunHandler(w http.ResponseWriter, r *http.Request) { // nolint: funlen
 	httpopts = httpopts.Init(url)
 	httpopts.ResetHeaders()
 	httpopts.DisableFastClient = stdClient
+	httpopts.SequentialWarmup = sequentialWarmup
 	httpopts.Insecure = httpsInsecure
 	httpopts.Resolve = resolve
 	if len(payload) > 0 {
diff --git a/ui/templates/main.html b/ui/templates/main.html
index 220e6e4..3c106d2 100644
--- a/ui/templates/main.html
+++ b/ui/templates/main.html
@@ -63,6 +63,7 @@
     tcp/udp/http: <input type="radio" name="runner" value="http" checked/>
     (https insecure:<input type="checkbox" name="https-insecure" />,
     standard go client instead of fastclient:<input type="checkbox" name="stdclient"/>,
+    sequential warmup: <input type="checkbox" name="sequential-warmup"/>,
     resolve: <input type="text" name="resolve" size="12" value="" />)
     <br />&nbsp;&nbsp;or<br />
     grpc: <input type="radio" name="runner" value="grpc"/>
diff --git a/ui/uihandler.go b/ui/uihandler.go
index d770aca..9718768 100644
--- a/ui/uihandler.go
+++ b/ui/uihandler.go
@@ -151,6 +151,7 @@ func Handler(w http.ResponseWriter, r *http.Request) {
 	grpcPing := (r.FormValue("ping") == "on")
 	grpcPingDelay, _ := time.ParseDuration(r.FormValue("grpc-ping-delay"))
 	stdClient := (r.FormValue("stdclient") == "on")
+	sequentialWarmup := (r.FormValue("sequential-warmup") == "on")
 	httpsInsecure := (r.FormValue("https-insecure") == "on")
 	resolve := r.FormValue("resolve")
 	timeoutStr := strings.TrimSpace(r.FormValue("timeout"))
@@ -209,6 +210,7 @@ func Handler(w http.ResponseWriter, r *http.Request) {
 	defaultHeaders := httpopts.AllHeaders()
 	httpopts.ResetHeaders()
 	httpopts.DisableFastClient = stdClient
+	httpopts.SequentialWarmup = sequentialWarmup
 	httpopts.Insecure = httpsInsecure
 	httpopts.Resolve = resolve
 	if len(payload) > 0 {


Test patch:
diff --git a/Dockerfile.test b/Dockerfile.test
index 00e7153..4465a70 100644
--- a/Dockerfile.test
+++ b/Dockerfile.test
@@ -1,5 +1,5 @@
 # Getting the source tree ready for running tests (sut)
-FROM docker.io/fortio/fortio.build:v37
+FROM docker.io/fortio/fortio.build:v38
 WORKDIR /go/src/fortio.org
 COPY . fortio
 RUN make -C fortio dependencies
diff --git a/Webtest.sh b/Webtest.sh
index 604399e..bb56483 100755
--- a/Webtest.sh
+++ b/Webtest.sh
@@ -115,7 +115,7 @@ docker exec $DOCKERNAME $FORTIO_BIN_PATH grpcping localhost
 PPROF_URL="$BASE_URL/debug/pprof/heap?debug=1"
 $CURL "$PPROF_URL" | grep -i TotalAlloc # should find this in memory profile
 # creating dummy container to hold a volume for test certs due to remote docker bind mount limitation.
-docker create -v $TEST_CERT_VOL --name $DOCKERSECVOLNAME docker.io/fortio/fortio.build:v37 /bin/true # cleaned up by name
+docker create -v $TEST_CERT_VOL --name $DOCKERSECVOLNAME docker.io/fortio/fortio.build:v38 /bin/true # cleaned up by name
 # copying cert files into the certs volume of the dummy container
 for f in ca.crt server.crt server.key; do docker cp "$PWD/cert-tmp/$f" "$DOCKERSECVOLNAME:$TEST_CERT_VOL/$f"; done
 # start server in secure grpc mode. uses non-default ports to avoid conflicts with fortio_server container.
diff --git a/fhttp/httprunner_test.go b/fhttp/httprunner_test.go
index a87a7c5..ddf5965 100644
--- a/fhttp/httprunner_test.go
+++ b/fhttp/httprunner_test.go
@@ -131,6 +131,37 @@ func TestHttpNotLeakingStdClient(t *testing.T) {
 	testHTTPNotLeaking(t, &HTTPRunnerOptions{HTTPOptions: HTTPOptions{DisableFastClient: true}})
 }
 
+func testPayloadWarmRace(t *testing.T, o *HTTPRunnerOptions) {
+	mux, addr := DynamicHTTPServer(false)
+	mux.HandleFunc("/echo123/", EchoHandler)
+	URL := fmt.Sprintf("http://localhost:%d/echo123/", addr.Port)
+	o.Init(URL)
+	o.NumConnections = 4
+	o.QPS = 16
+	o.Duration = 2 * time.Second
+	o.Payload = []byte("abc")
+	res, err := RunHTTPTest(o)
+	if err != nil {
+		t.Error(err)
+		return
+	}
+	totalReq := res.DurationHistogram.Count
+	httpOk := res.RetCodes[http.StatusOK]
+	if totalReq != httpOk {
+		t.Errorf("Mismatch between requests %d and ok %v", totalReq, res.RetCodes)
+	}
+}
+
+func TestPayloadWarmRaceStdClient(t *testing.T) {
+	testPayloadWarmRace(t, &HTTPRunnerOptions{HTTPOptions: HTTPOptions{DisableFastClient: true}})
+	testPayloadWarmRace(t, &HTTPRunnerOptions{HTTPOptions: HTTPOptions{DisableFastClient: true, SequentialWarmup: true}})
+}
+
+func TestPayloadWarmRaceFastClient(t *testing.T) {
+	testPayloadWarmRace(t, &HTTPRunnerOptions{})
+	testPayloadWarmRace(t, &HTTPRunnerOptions{HTTPOptions: HTTPOptions{SequentialWarmup: true}})
+}
+
 func TestHTTPRunnerClientRace(t *testing.T) {
 	mux, addr := DynamicHTTPServer(false)
 	mux.HandleFunc("/echo1/", EchoHandler)