5
0
mirror of https://github.com/wailsapp/wails.git synced 2025-05-02 18:10:48 +08:00
wails/v2/internal/frontend/desktop/darwin/single_instance.go
Andrey Pshenkin 426a569c89
Fix single instance lock for macOS sandbox app (#3029)
* fix single instance lock for sandbox app

* fix single instance lock for sandbox app
2023-11-05 14:10:01 +11:00

93 lines
2.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//go:build darwin
// +build darwin
package darwin
/*
#cgo CFLAGS: -x objective-c
#cgo LDFLAGS: -framework Foundation -framework Cocoa
#import "AppDelegate.h"
*/
import "C"
import (
"encoding/json"
"fmt"
"github.com/wailsapp/wails/v2/pkg/options"
"os"
"strings"
"syscall"
"unsafe"
)
func SetupSingleInstance(uniqueID string) {
lockFilePath := getTempDir()
lockFileName := uniqueID + ".lock"
_, err := createLockFile(lockFilePath + "/" + lockFileName)
// if lockFile exist send notification to second instance
if err != nil {
c := NewCalloc()
defer c.Free()
singleInstanceUniqueId := c.String(uniqueID)
data, err := options.NewSecondInstanceData()
if err != nil {
return
}
serialized, err := json.Marshal(data)
if err != nil {
return
}
C.SendDataToFirstInstance(singleInstanceUniqueId, c.String(string(serialized)))
os.Exit(0)
}
}
//export HandleSecondInstanceData
func HandleSecondInstanceData(secondInstanceMessage *C.char) {
message := C.GoString(secondInstanceMessage)
var secondInstanceData options.SecondInstanceData
err := json.Unmarshal([]byte(message), &secondInstanceData)
if err == nil {
secondInstanceBuffer <- secondInstanceData
}
}
// CreateLockFile tries to create a file with given name and acquire an
// exclusive lock on it. If the file already exists AND is still locked, it will
// fail.
func createLockFile(filename string) (*os.File, error) {
file, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE, 0600)
if err != nil {
fmt.Printf("Failed to open lockfile %s: %s", filename, err)
return nil, err
}
err = syscall.Flock(int(file.Fd()), syscall.LOCK_EX|syscall.LOCK_NB)
if err != nil {
// Flock failed for some other reason than other instance already lock it. Print it in logs for possible debugging.
if !strings.Contains(err.Error(), "resource temporarily unavailable") {
fmt.Printf("Failed to lock lockfile %s: %s", filename, err)
}
file.Close()
return nil, err
}
return file, nil
}
// If app is sandboxed, golang os.TempDir() will return path that will not be accessible. So use native macOS temp dir function.
func getTempDir() string {
cstring := C.GetMacOsNativeTempDir()
path := C.GoString(cstring)
C.free(unsafe.Pointer(cstring))
return path
}