prevent multiple instances in same namespace
This commit is contained in:
parent
c2f17beff5
commit
77821a7d01
|
|
@ -34,6 +34,7 @@ import (
|
||||||
"denote/internal/disk"
|
"denote/internal/disk"
|
||||||
"denote/pkg/encoding/results"
|
"denote/pkg/encoding/results"
|
||||||
"denote/pkg/metadata"
|
"denote/pkg/metadata"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
|
|
@ -41,6 +42,7 @@ import (
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"9fans.net/go/plan9"
|
"9fans.net/go/plan9"
|
||||||
|
|
@ -165,14 +167,36 @@ func StartServer(initialData metadata.Results, denoteDir string, callbacks Callb
|
||||||
|
|
||||||
sockPath := ns + "/denote"
|
sockPath := ns + "/denote"
|
||||||
|
|
||||||
// Remove old socket if it exists
|
// Try to create Unix domain socket listener
|
||||||
os.Remove(sockPath)
|
// Use stale socket detection like acme (see /usr/local/plan9/src/lib9/announce.c)
|
||||||
|
var listener net.Listener
|
||||||
|
var err error
|
||||||
|
for attempts := 0; attempts < 2; attempts++ {
|
||||||
|
listener, err = net.Listen("unix", sockPath)
|
||||||
|
if err == nil {
|
||||||
|
break // Successfully bound to socket
|
||||||
|
}
|
||||||
|
|
||||||
// Create Unix domain socket listener
|
// Check if error is "address already in use"
|
||||||
listener, err := net.Listen("unix", sockPath)
|
if errors.Is(err, syscall.EADDRINUSE) {
|
||||||
if err != nil {
|
// Try to connect to see if socket is live or stale
|
||||||
|
conn, dialErr := net.Dial("unix", sockPath)
|
||||||
|
if dialErr == nil {
|
||||||
|
// Connection succeeded - another instance is running
|
||||||
|
conn.Close()
|
||||||
|
return fmt.Errorf("Denote already running in this namespace")
|
||||||
|
}
|
||||||
|
// Connection failed - socket is stale, remove it and retry
|
||||||
|
os.Remove(sockPath)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Some other error
|
||||||
return fmt.Errorf("failed to listen on socket: %w", err)
|
return fmt.Errorf("failed to listen on socket: %w", err)
|
||||||
}
|
}
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to listen on socket after cleanup: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
// Start accepting connections in background
|
// Start accepting connections in background
|
||||||
go srv.acceptLoop(listener)
|
go srv.acceptLoop(listener)
|
||||||
|
|
|
||||||
17
main.go
17
main.go
|
|
@ -243,14 +243,25 @@ func main() {
|
||||||
|
|
||||||
// 9p server startup with pre-loaded data and callbacks
|
// 9p server startup with pre-loaded data and callbacks
|
||||||
if err := p9server.StartServer(notes, denoteDir, callbacks); err != nil {
|
if err := p9server.StartServer(notes, denoteDir, callbacks); err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "warning: failed to start fileserver: %v\n", err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// start acme log watcher
|
// start acme log watcher
|
||||||
go disk.WatchAcmeLog()
|
go disk.WatchAcmeLog()
|
||||||
|
|
||||||
// open window
|
// open window - look for existing /Denote/ window across all processes
|
||||||
if w = acme.Show(wname); w == nil {
|
if wins, err := acme.Windows(); err == nil {
|
||||||
|
for _, winInfo := range wins {
|
||||||
|
if winInfo.Name == wname {
|
||||||
|
// Found existing window, open it
|
||||||
|
if w, err = acme.Open(winInfo.ID, nil); err == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If no existing window found, create new one
|
||||||
|
if w == nil {
|
||||||
if w, err = acme.New(); err != nil {
|
if w, err = acme.New(); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue