-
Notifications
You must be signed in to change notification settings - Fork 785
Fix bugs with connection switching #2957
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -19,6 +19,7 @@ import ( | |
| "github.com/wavetermdev/waveterm/pkg/jobcontroller" | ||
| "github.com/wavetermdev/waveterm/pkg/remote" | ||
| "github.com/wavetermdev/waveterm/pkg/remote/conncontroller" | ||
| "github.com/wavetermdev/waveterm/pkg/util/ds" | ||
| "github.com/wavetermdev/waveterm/pkg/util/shellutil" | ||
| "github.com/wavetermdev/waveterm/pkg/wavebase" | ||
| "github.com/wavetermdev/waveterm/pkg/waveobj" | ||
|
|
@@ -75,10 +76,17 @@ type Controller interface { | |
|
|
||
| // Registry for all controllers | ||
| var ( | ||
| controllerRegistry = make(map[string]Controller) | ||
| registryLock sync.RWMutex | ||
| controllerRegistry = make(map[string]Controller) | ||
| registryLock sync.RWMutex | ||
| blockResyncMutexMap = ds.MakeSyncMap[*sync.Mutex]() | ||
| ) | ||
|
|
||
| func getBlockResyncMutex(blockId string) *sync.Mutex { | ||
| return blockResyncMutexMap.GetOrCreate(blockId, func() *sync.Mutex { | ||
| return &sync.Mutex{} | ||
| }) | ||
| } | ||
|
|
||
| // Registry operations | ||
| func getController(blockId string) Controller { | ||
| registryLock.RLock() | ||
|
|
@@ -145,6 +153,10 @@ func ResyncController(ctx context.Context, tabId string, blockId string, rtOpts | |
| return fmt.Errorf("invalid tabId or blockId passed to ResyncController") | ||
| } | ||
|
|
||
| mu := getBlockResyncMutex(blockId) | ||
| mu.Lock() | ||
| defer mu.Unlock() | ||
|
|
||
|
Comment on lines
+156
to
+159
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
# Show key mutation paths for a block controller lifecycle.
rg -n --type=go '\bfunc\s+ResyncController\b|\bfunc\s+DestroyBlockController\b|\bfunc\s+handleBlockCloseEvent\b' -A35 -B5 pkg/blockcontroller/blockcontroller.go
# Show where block-scoped mutex is actually acquired.
rg -n --type=go '\bgetBlockResyncMutex\s*\(' -C2 pkg/blockcontroller/blockcontroller.goRepository: wavetermdev/waveterm Length of output: 3247 🏁 Script executed: #!/bin/bash
set -euo pipefail
# Find all callers of DestroyBlockController
rg -n --type=go '\bDestroyBlockController\s*\(' pkg/blockcontroller/blockcontroller.go
# Check the full ResyncController function to see all call sites
sed -n '151,200p' pkg/blockcontroller/blockcontroller.go
# Check if there are any other files calling DestroyBlockController
rg -l --type=go '\bDestroyBlockController\s*\(' pkg/Repository: wavetermdev/waveterm Length of output: 2129 🏁 Script executed: #!/bin/bash
set -euo pipefail
# Check callers in other files
rg -n --type=go '\bDestroyBlockController\s*\(' pkg/wshrpc/wshserver/wshserver.go pkg/service/workspaceservice/workspaceservice.go -B3 -A3
# Also check the full context around DestroyBlockController definition
sed -n '295,303p' pkg/blockcontroller/blockcontroller.goRepository: wavetermdev/waveterm Length of output: 1274 🏁 Script executed: #!/bin/bash
set -euo pipefail
# Check getController and deleteController implementations to understand what state they protect
sed -n '1,100p' pkg/blockcontroller/blockcontroller.go | grep -A10 'func getController\|func deleteController\|blockResyncMutexMap\|var '
# Get the full beginning of the file to see global state and any other synchronization
head -100 pkg/blockcontroller/blockcontroller.goRepository: wavetermdev/waveterm Length of output: 3519 Per-block serialization is incomplete without locking
Make 🤖 Prompt for AI Agents |
||
| blockData, err := wstore.DBMustGet[*waveobj.Block](ctx, blockId) | ||
| if err != nil { | ||
| return fmt.Errorf("error getting block: %w", err) | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Repository: wavetermdev/waveterm
Length of output: 826
🏁 Script executed:
Repository: wavetermdev/waveterm
Length of output: 1683
🏁 Script executed:
Repository: wavetermdev/waveterm
Length of output: 3745
🏁 Script executed:
Repository: wavetermdev/waveterm
Length of output: 2489
blockResyncMutexMaphas no cleanup for deleted blocks, causing unbounded map growth.When blocks are deleted via
DeleteBlock(), their corresponding mutex entries remain inblockResyncMutexMapindefinitely. Since blocks are frequently created and deleted throughout the application lifecycle, this creates a memory leak with monotonic map growth.Consider either:
DeleteBlock()with ref-counted or weak references to lock entries🤖 Prompt for AI Agents