From c5a0a0fc27730607f03e65ca4d2aba7096c70547 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E8=81=AA?= Date: Mon, 1 Aug 2022 17:04:39 +0800 Subject: [PATCH] fix: pluginMap uses sync.Map to avoid data race --- hrp/boomer.go | 14 ++++++++------ hrp/plugin.go | 9 +++++---- hrp/runner.go | 8 +++++--- hrp/runner_test.go | 2 +- 4 files changed, 19 insertions(+), 14 deletions(-) diff --git a/hrp/boomer.go b/hrp/boomer.go index 34f63fc7..d5d71f47 100644 --- a/hrp/boomer.go +++ b/hrp/boomer.go @@ -101,11 +101,12 @@ func (b *HRPBoomer) Run(testcases ...ITestCase) { // quit all plugins defer func() { - if len(pluginMap) > 0 { - for _, plugin := range pluginMap { + pluginMap.Range(func(key, value interface{}) bool { + if plugin, ok := value.(funplugin.IPlugin); ok { plugin.Quit() } - } + return true + }) }() taskSlice := b.ConvertTestCasesToBoomerTasks(testcases...) @@ -283,11 +284,12 @@ func (b *HRPBoomer) PollTasks(ctx context.Context) { func (b *HRPBoomer) PollTestCases(ctx context.Context) { // quit all plugins defer func() { - if len(pluginMap) > 0 { - for _, plugin := range pluginMap { + pluginMap.Range(func(key, value interface{}) bool { + if plugin, ok := value.(funplugin.IPlugin); ok { plugin.Quit() } - } + return true + }) }() for { diff --git a/hrp/plugin.go b/hrp/plugin.go index d98437ac..c762b6c8 100644 --- a/hrp/plugin.go +++ b/hrp/plugin.go @@ -5,6 +5,7 @@ import ( "os" "path/filepath" "strings" + "sync" "github.com/httprunner/funplugin" "github.com/httprunner/funplugin/fungo" @@ -24,7 +25,7 @@ const ( const projectInfoFile = "proj.json" // used for ensuring root project -var pluginMap = map[string]funplugin.IPlugin{} // used for reusing plugin instance +var pluginMap = sync.Map{} // used for reusing plugin instance func initPlugin(path, venv string, logOn bool) (plugin funplugin.IPlugin, err error) { // plugin file not found @@ -37,8 +38,8 @@ func initPlugin(path, venv string, logOn bool) (plugin funplugin.IPlugin, err er } // reuse plugin instance if it already initialized - if p, ok := pluginMap[pluginPath]; ok { - return p, nil + if p, ok := pluginMap.Load(pluginPath); ok { + return p.(funplugin.IPlugin), nil } pluginOptions := []funplugin.Option{funplugin.WithLogOn(logOn)} @@ -74,7 +75,7 @@ func initPlugin(path, venv string, logOn bool) (plugin funplugin.IPlugin, err er } // add plugin instance to plugin map - pluginMap[pluginPath] = plugin + pluginMap.Store(pluginPath, plugin) // report event for initializing plugin event := sdk.EventTracking{ diff --git a/hrp/runner.go b/hrp/runner.go index b9192e09..cff1091f 100644 --- a/hrp/runner.go +++ b/hrp/runner.go @@ -17,6 +17,7 @@ import ( "github.com/rs/zerolog/log" "golang.org/x/net/http2" + "github.com/httprunner/funplugin" "github.com/httprunner/httprunner/v4/hrp/internal/builtin" "github.com/httprunner/httprunner/v4/hrp/internal/sdk" ) @@ -188,11 +189,12 @@ func (r *HRPRunner) Run(testcases ...ITestCase) error { // quit all plugins defer func() { - if len(pluginMap) > 0 { - for _, plugin := range pluginMap { + pluginMap.Range(func(key, value interface{}) bool { + if plugin, ok := value.(funplugin.IPlugin); ok { plugin.Quit() } - } + return true + }) }() var runErr error diff --git a/hrp/runner_test.go b/hrp/runner_test.go index 6b92fdf5..383cae09 100644 --- a/hrp/runner_test.go +++ b/hrp/runner_test.go @@ -24,7 +24,7 @@ func removeHashicorpGoPlugin() { log.Info().Msg("[teardown] remove hashicorp go plugin") os.Remove(tmpl("debugtalk.bin")) pluginPath, _ := filepath.Abs(tmpl("debugtalk.bin")) - delete(pluginMap, pluginPath) + pluginMap.Delete(pluginPath) } func buildHashicorpPyPlugin() {