How to cancel goroutines after a certain amount of time
I am making a load testing tool that makes multiple HTTP calls to goroutines and it works, but now I am trying to only allow it to run for a certain duration.
How can I cancel goroutines when sleep is over?
I am currently trying to make a goroutine that executes time.Sleep()
for the duration specified and when that is complete it will broadcast a message to the channel.
In my endless loop, I listen to the message in the switch statement, and when it's there, I come back. This works the way I want.
The problem is goroutines from the string go httpPost()
will keep making HTTP calls. I even try to pipe a pipe to this function and listen to the same message there CALL_TIME_RAN_OUT
, but for whatever reason, when I do this, the goroutines only run once and then return immediately, as opposed to waiting for the message to be broadcast to the end Sleep
.
Does anyone know a better approach I can take? It doesn't seem to work.
Here's the code (removed irrelevant parts):
func attack(cfg AttackConfig) {
// some code ...
var ar attackResponse
ch := make(chan uint8, 8)
go func() {
time.Sleep(cfg.Duration * time.Second)
ch <- CALL_TIME_RAN_OUT
}()
for {
if atomic.LoadInt32(&currConnections) < atomic.LoadInt32(&maxConnections) - 1 {
go httpPost(cfg, &ar, ch)
}
switch <-ch {
// some other cases ...
case CALL_TIME_RAN_OUT:
fmt.Printf("%d seconds have elapsed. Shutting down!", cfg.Duration)
return
}
}
}
func httpPost(cfg AttackConfig, a *attackResponse, ch chan uint8) {
// some code here to create HTTP client ...
for {
// some code to make HTTP call ...
switch <-ch {
case CALL_TIME_RAN_OUT:
return
}
}
}
source to share
use the package golang.org/x/net/context
. Go 1.7 moves the package golang.org/x/net/context
to the standard library as context
. So it's easy import context
if you are using version 1.7+.
usage is simple:
package main
import (
"context"
"fmt"
"time"
)
func test(ctx context.Context) {
t := time.Now()
select {
case <-time.After(1 * time.Second):
fmt.Println("overslept")
case <-ctx.Done():
}
fmt.Println("used:", time.Since(t))
}
func main() {
ctx, _ := context.WithTimeout(context.Background(), 50*time.Millisecond)
test(ctx)
}
source to share