mirror of
https://github.com/wavetermdev/waveterm.git
synced 2024-12-21 16:38:23 +01:00
fix bcstart -- don't allow two controllers to start simultaneously (#1418)
This commit is contained in:
parent
6dfc85b324
commit
00e3c4ec75
@ -13,6 +13,7 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/wavetermdev/waveterm/pkg/filestore"
|
"github.com/wavetermdev/waveterm/pkg/filestore"
|
||||||
@ -77,6 +78,7 @@ type BlockController struct {
|
|||||||
ShellInputCh chan *BlockInputUnion
|
ShellInputCh chan *BlockInputUnion
|
||||||
ShellProcStatus string
|
ShellProcStatus string
|
||||||
ShellProcExitCode int
|
ShellProcExitCode int
|
||||||
|
RunLock *atomic.Bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type BlockControllerRuntimeStatus struct {
|
type BlockControllerRuntimeStatus struct {
|
||||||
@ -492,7 +494,9 @@ func (bc *BlockController) DoRunShellCommand(rc *RunShellOpts, blockMeta waveobj
|
|||||||
defer func() {
|
defer func() {
|
||||||
wshutil.DefaultRouter.UnregisterRoute(wshutil.MakeControllerRouteId(bc.BlockId))
|
wshutil.DefaultRouter.UnregisterRoute(wshutil.MakeControllerRouteId(bc.BlockId))
|
||||||
bc.UpdateControllerAndSendUpdate(func() bool {
|
bc.UpdateControllerAndSendUpdate(func() bool {
|
||||||
bc.ShellProcStatus = Status_Done
|
if bc.ShellProcStatus == Status_Running {
|
||||||
|
bc.ShellProcStatus = Status_Done
|
||||||
|
}
|
||||||
bc.ShellProcExitCode = exitCode
|
bc.ShellProcExitCode = exitCode
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
@ -568,7 +572,31 @@ func setTermSize(ctx context.Context, blockId string, termSize waveobj.TermSize)
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (bc *BlockController) LockRunLock() bool {
|
||||||
|
rtn := bc.RunLock.CompareAndSwap(false, true)
|
||||||
|
if rtn {
|
||||||
|
log.Printf("block %q run() lock\n", bc.BlockId)
|
||||||
|
}
|
||||||
|
return rtn
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bc *BlockController) UnlockRunLock() {
|
||||||
|
bc.RunLock.Store(false)
|
||||||
|
log.Printf("block %q run() unlock\n", bc.BlockId)
|
||||||
|
}
|
||||||
|
|
||||||
func (bc *BlockController) run(bdata *waveobj.Block, blockMeta map[string]any, rtOpts *waveobj.RuntimeOpts, force bool) {
|
func (bc *BlockController) run(bdata *waveobj.Block, blockMeta map[string]any, rtOpts *waveobj.RuntimeOpts, force bool) {
|
||||||
|
runningShellCommand := false
|
||||||
|
ok := bc.LockRunLock()
|
||||||
|
if !ok {
|
||||||
|
log.Printf("block %q is already executing run()\n", bc.BlockId)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
if !runningShellCommand {
|
||||||
|
bc.UnlockRunLock()
|
||||||
|
}
|
||||||
|
}()
|
||||||
curStatus := bc.GetRuntimeStatus()
|
curStatus := bc.GetRuntimeStatus()
|
||||||
controllerName := bdata.Meta.GetString(waveobj.MetaKey_Controller, "")
|
controllerName := bdata.Meta.GetString(waveobj.MetaKey_Controller, "")
|
||||||
if controllerName != BlockController_Shell && controllerName != BlockController_Cmd {
|
if controllerName != BlockController_Shell && controllerName != BlockController_Cmd {
|
||||||
@ -597,8 +625,10 @@ func (bc *BlockController) run(bdata *waveobj.Block, blockMeta map[string]any, r
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
runningShellCommand = true
|
||||||
go func() {
|
go func() {
|
||||||
defer panichandler.PanicHandler("blockcontroller:run-shell-command")
|
defer panichandler.PanicHandler("blockcontroller:run-shell-command")
|
||||||
|
defer bc.UnlockRunLock()
|
||||||
var termSize waveobj.TermSize
|
var termSize waveobj.TermSize
|
||||||
if rtOpts != nil {
|
if rtOpts != nil {
|
||||||
termSize = rtOpts.TermSize
|
termSize = rtOpts.TermSize
|
||||||
@ -658,7 +688,7 @@ func CheckConnStatus(blockId string) error {
|
|||||||
func (bc *BlockController) StopShellProc(shouldWait bool) {
|
func (bc *BlockController) StopShellProc(shouldWait bool) {
|
||||||
bc.Lock.Lock()
|
bc.Lock.Lock()
|
||||||
defer bc.Lock.Unlock()
|
defer bc.Lock.Unlock()
|
||||||
if bc.ShellProc == nil || bc.ShellProcStatus == Status_Done {
|
if bc.ShellProc == nil || bc.ShellProcStatus == Status_Done || bc.ShellProcStatus == Status_Init {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
bc.ShellProc.Close()
|
bc.ShellProc.Close()
|
||||||
@ -689,6 +719,7 @@ func getOrCreateBlockController(tabId string, blockId string, controllerName str
|
|||||||
TabId: tabId,
|
TabId: tabId,
|
||||||
BlockId: blockId,
|
BlockId: blockId,
|
||||||
ShellProcStatus: Status_Init,
|
ShellProcStatus: Status_Init,
|
||||||
|
RunLock: &atomic.Bool{},
|
||||||
}
|
}
|
||||||
blockControllerMap[blockId] = bc
|
blockControllerMap[blockId] = bc
|
||||||
createdController = true
|
createdController = true
|
||||||
@ -716,11 +747,13 @@ func ResyncController(ctx context.Context, tabId string, blockId string, rtOpts
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
// check if conn is different, if so, stop the current controller
|
log.Printf("resync controller %s %q (%q) (force %v)\n", blockId, controllerName, connName, force)
|
||||||
|
// check if conn is different, if so, stop the current controller, and set status back to init
|
||||||
if curBc != nil {
|
if curBc != nil {
|
||||||
bcStatus := curBc.GetRuntimeStatus()
|
bcStatus := curBc.GetRuntimeStatus()
|
||||||
if bcStatus.ShellProcStatus == Status_Running && bcStatus.ShellProcConnName != connName {
|
if bcStatus.ShellProcStatus == Status_Running && bcStatus.ShellProcConnName != connName {
|
||||||
StopBlockController(blockId)
|
log.Printf("stopping blockcontroller %s due to conn change\n", blockId)
|
||||||
|
StopBlockControllerAndSetStatus(blockId, Status_Init)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// now if there is a conn, ensure it is connected
|
// now if there is a conn, ensure it is connected
|
||||||
@ -754,20 +787,20 @@ func startBlockController(ctx context.Context, tabId string, blockId string, rtO
|
|||||||
return fmt.Errorf("unknown controller %q", controllerName)
|
return fmt.Errorf("unknown controller %q", controllerName)
|
||||||
}
|
}
|
||||||
connName := blockData.Meta.GetString(waveobj.MetaKey_Connection, "")
|
connName := blockData.Meta.GetString(waveobj.MetaKey_Connection, "")
|
||||||
log.Printf("start blockcontroller %s %q (%q)\n", blockId, controllerName, connName)
|
|
||||||
err = CheckConnStatus(blockId)
|
err = CheckConnStatus(blockId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("cannot start shellproc: %w", err)
|
return fmt.Errorf("cannot start shellproc: %w", err)
|
||||||
}
|
}
|
||||||
bc := getOrCreateBlockController(tabId, blockId, controllerName)
|
bc := getOrCreateBlockController(tabId, blockId, controllerName)
|
||||||
bcStatus := bc.GetRuntimeStatus()
|
bcStatus := bc.GetRuntimeStatus()
|
||||||
|
log.Printf("start blockcontroller %s %q (%q) (curstatus %s) (force %v)\n", blockId, controllerName, connName, bcStatus.ShellProcStatus, force)
|
||||||
if bcStatus.ShellProcStatus == Status_Init || bcStatus.ShellProcStatus == Status_Done {
|
if bcStatus.ShellProcStatus == Status_Init || bcStatus.ShellProcStatus == Status_Done {
|
||||||
go bc.run(blockData, blockData.Meta, rtOpts, force)
|
go bc.run(blockData, blockData.Meta, rtOpts, force)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func StopBlockController(blockId string) {
|
func StopBlockControllerAndSetStatus(blockId string, newStatus string) {
|
||||||
bc := GetBlockController(blockId)
|
bc := GetBlockController(blockId)
|
||||||
if bc == nil {
|
if bc == nil {
|
||||||
return
|
return
|
||||||
@ -776,13 +809,17 @@ func StopBlockController(blockId string) {
|
|||||||
bc.ShellProc.Close()
|
bc.ShellProc.Close()
|
||||||
<-bc.ShellProc.DoneCh
|
<-bc.ShellProc.DoneCh
|
||||||
bc.UpdateControllerAndSendUpdate(func() bool {
|
bc.UpdateControllerAndSendUpdate(func() bool {
|
||||||
bc.ShellProcStatus = Status_Done
|
bc.ShellProcStatus = newStatus
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func StopBlockController(blockId string) {
|
||||||
|
StopBlockControllerAndSetStatus(blockId, Status_Done)
|
||||||
|
}
|
||||||
|
|
||||||
func getControllerList() []*BlockController {
|
func getControllerList() []*BlockController {
|
||||||
globalLock.Lock()
|
globalLock.Lock()
|
||||||
defer globalLock.Unlock()
|
defer globalLock.Unlock()
|
||||||
|
@ -49,7 +49,6 @@ func (cs *ClientService) GetAllConnStatus(ctx context.Context) ([]wshrpc.ConnSta
|
|||||||
|
|
||||||
// moves the window to the front of the windowId stack
|
// moves the window to the front of the windowId stack
|
||||||
func (cs *ClientService) FocusWindow(ctx context.Context, windowId string) error {
|
func (cs *ClientService) FocusWindow(ctx context.Context, windowId string) error {
|
||||||
log.Printf("FocusWindow %s\n", windowId)
|
|
||||||
return wcore.FocusWindow(ctx, windowId)
|
return wcore.FocusWindow(ctx, windowId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user