From 3a01e835a19d2c10aafbad83eb5e11a0c2fc4254 Mon Sep 17 00:00:00 2001 From: chris bell Date: Sat, 6 Jun 2026 15:48:43 -0500 Subject: [PATCH] Cleanup; Adding locks where needed, and checking port availibility --- daemon.go | 49 ++++++++++++++++++++++++++++++++++++++++++++++++- instance.go | 11 ----------- 2 files changed, 48 insertions(+), 12 deletions(-) diff --git a/daemon.go b/daemon.go index 1d72c87..5de396b 100644 --- a/daemon.go +++ b/daemon.go @@ -6,6 +6,7 @@ import ( "net/http" "os" "os/signal" + "path/filepath" "strconv" "sync" "syscall" @@ -24,6 +25,7 @@ type InstanceStatusResponse struct { } type DaemonServer struct { + sync.RWMutex cfg *AppConfig configPath string procManager *ProcessManager @@ -82,6 +84,19 @@ func StartDaemon(cfg *AppConfig, configPath string) error { return nil } +func (ds *DaemonServer) reloadConfig() error { + cfg, err := LoadOrCreateConfig(ds.configPath) + if err != nil { + fmt.Printf("Could not reload configuration file: %v\n", err) + return err + } + + ds.Lock() + defer ds.Unlock() + ds.cfg = cfg + return nil +} + func (ds *DaemonServer) shutdownAllRunningServers() { ds.procManager.Lock() @@ -157,11 +172,26 @@ func (ds *DaemonServer) handleCreate(w http.ResponseWriter, r *http.Request) { return } + if ds.reloadConfig() != nil { + http.Error(w, "Could not reload config", http.StatusInternalServerError) + return + } + + ds.Lock() + defer ds.Unlock() + if _, exists := ds.cfg.Instances[name]; exists { http.Error(w, fmt.Sprintf("Instance '%s' already exists in configuration", name), http.StatusConflict) return } + for name, options := range ds.cfg.Instances { + if options.Port == converted_port { + http.Error(w, fmt.Sprintf("Port already occupied by instance '%s'", name), http.StatusConflict) + return + } + } + options := VsServerConfigOptions{ Version: version, ServerName: name, @@ -199,6 +229,7 @@ func (ds *DaemonServer) handleCreate(w http.ResponseWriter, r *http.Request) { } func (ds *DaemonServer) handleStart(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) return @@ -210,13 +241,21 @@ func (ds *DaemonServer) handleStart(w http.ResponseWriter, r *http.Request) { return } + if ds.reloadConfig() != nil { + http.Error(w, "Could not reload config", http.StatusInternalServerError) + return + } + + ds.RLock() + defer ds.RUnlock() + options, exists := ds.cfg.Instances[name] if !exists { http.Error(w, fmt.Sprintf("Instance '%s' does not exist. Run 'create' first", name), http.StatusNotFound) return } - instanceConfigPath := ds.configPath + instanceConfigPath := filepath.Join(ds.cfg.Storage.InstancesDir, name, "serverconfig.json") err := SyncInstanceConfig(options.Version, instanceConfigPath, options, ds.cfg) if err != nil { http.Error(w, "Failed to sync config: "+err.Error(), http.StatusInternalServerError) @@ -289,6 +328,14 @@ func (ds *DaemonServer) handleList(w http.ResponseWriter, r *http.Request) { return } + if ds.reloadConfig() != nil { + http.Error(w, "Could not reload config", http.StatusInternalServerError) + return + } + + ds.RLock() + defer ds.RUnlock() + ds.procManager.RLock() defer ds.procManager.RUnlock() diff --git a/instance.go b/instance.go index 6746000..3d5c13f 100644 --- a/instance.go +++ b/instance.go @@ -3,7 +3,6 @@ package main import ( "fmt" "os" - "os/exec" "path/filepath" ) @@ -14,16 +13,6 @@ const ( StateRunning InstanceState = "RUNNING" ) -type ManagedInstance struct { - Name string `json:"name"` - Version string `json:"version"` - Port int `json:"port"` - Status InstanceState `json:"status"` - - Cmd *exec.Cmd `json:"-"` - Stdin interface{} `json:"-"` -} - func CreateNewInstance(name string, version string, options VsServerConfigOptions, cfg *AppConfig) error { instanceDir := filepath.Join(cfg.Storage.InstancesDir, name)