-
Notifications
You must be signed in to change notification settings - Fork 3k
Closed
Description
Cobra has a global map here to store completion function when those exists.
This global map is not protected in any way, which leads to fatal error: concurrent map writes
when handling multiple root command concurrently. Yes, it's a little odd situation but it's a useful one to generate documentation/completion faster (ie, concurrently). Most of those documentation/completion generator will actually mutate things here and there in the commands, which makes them not thread-safe. Now, this global map for completion functions also make things no, thread-safe, even if you duplicated entirely your root command.
I see the following possible solutions:
- move this completion function (no map anymore) directly into
flag.Flag
. No more global, no more indirection, but that's another package. - move the map into
cobra.Command
, to at least make be thread-safe when you have a copy of yourCommand
- add a mutex or use
sync.Map
.
Example code to trigger the issue:
package main
import (
"fmt"
"sync"
"github.com/spf13/cobra"
)
func main() {
cmd := cobra.Command{}
N := 2
options := make([]string, N)
var wg sync.WaitGroup
for i := 0; i < N; i++ {
flag := fmt.Sprintf("flag%d", i)
cmd.Flags().StringVarP(&options[i], flag, "", "value", "usage")
wg.Add(1)
go func() {
defer wg.Done()
err := cmd.RegisterFlagCompletionFunc(flag, nil)
if err != nil {
panic(err)
}
}()
}
wg.Wait()
}
Originally posted by @krobelus in #1290 (comment)
krobelus and silenceshell
Metadata
Metadata
Assignees
Labels
No labels