on main help sign in
fix: potential data race on `permissionService` (#2964)
commit6b312bee06bf3ca90ba587035a7287594b97e186 authormei2jun1 <jun.mei@ucloud.cn> dateWed 20 May 2026, 21:10 (5 months ago) parent54f68fc
2 files changed+23−6
internal/permission/permission.go+8−6 internal/permission/permission_test.go+15
internal/permission/permission.go+8−6
@@ -6,6 +6,7 @@ import (
66 "path/filepath"
77 "slices"
88 "sync"
9+ "sync/atomic"
910
1011 "github.com/charmbracelet/crush/internal/csync"
1112 "github.com/charmbracelet/crush/internal/pubsub"
@@ -90,7 +91,7 @@ type permissionService struct {
9091 pendingRequests *csync.Map[string, chan bool]
9192 autoApproveSessions map[string]bool
9293 autoApproveSessionsMu sync.RWMutex
93− skip bool
94+ skip atomic.Bool
9495 allowedTools []string
9596
9697 // used to make sure we only process one request at a time
@@ -159,7 +160,7 @@ func (s *permissionService) Deny(permission PermissionRequest) {
159160}
160161
161162func (s *permissionService) Request(ctx context.Context, opts CreatePermissionRequest) (bool, error) {
162− if s.skip {
163+ if s.skip.Load() {
163164 return true, nil
164165 }
165166
@@ -268,22 +269,23 @@ func (s *permissionService) SubscribeNotifications(ctx context.Context) <-chan p
268269}
269270
270271func (s *permissionService) SetSkipRequests(skip bool) {
271− s.skip = skip
272+ s.skip.Store(skip)
272273}
273274
274275func (s *permissionService) SkipRequests() bool {
275− return s.skip
276+ return s.skip.Load()
276277}
277278
278279func NewPermissionService(workingDir string, skip bool, allowedTools []string) Service {
279− return &permissionService{
280+ svc := &permissionService{
280281 Broker: pubsub.NewBroker[PermissionRequest](),
281282 notificationBroker: pubsub.NewBroker[PermissionNotification](),
282283 workingDir: workingDir,
283284 sessionPermissions: csync.NewMap[PermissionKey, bool](),
284285 autoApproveSessions: make(map[string]bool),
285− skip: skip,
286286 allowedTools: allowedTools,
287287 pendingRequests: csync.NewMap[string, chan bool](),
288288 }
289+ svc.skip.Store(skip)
290+ return svc
289291}
internal/permission/permission_test.go+15
@@ -79,6 +79,21 @@ func TestPermissionService_AllowedCommands(t *testing.T) {
7979 }
8080}
8181
82+func TestSkipRace(t *testing.T) {
83+ svc := NewPermissionService("/tmp", false, nil)
84+ var wg sync.WaitGroup
85+ wg.Add(2)
86+ go func() {
87+ defer wg.Done()
88+ svc.SetSkipRequests(true)
89+ }()
90+ go func() {
91+ defer wg.Done()
92+ svc.SkipRequests()
93+ }()
94+ wg.Wait()
95+}
96+
8297func TestPermissionService_SkipMode(t *testing.T) {
8398 service := NewPermissionService("/tmp", true, []string{})
8499