refactor for Windows compatibility

This commit is contained in:
gengbing
2021-07-07 13:27:19 +08:00
parent 0fd237d563
commit c4183ec8a5
6 changed files with 57 additions and 36 deletions

View File

@@ -62,12 +62,12 @@ A plugin must have the following functions defined in its root package.
// OnLoad gets called after all plugins are successfully loaded and all dependencies are
// properly initialized.
func OnLoad(data interface{}) error {
return nil
return nil
}
// OnInit gets called after the execution of all OnLoad functions.
func OnInit(sharedVault *vault.Vault) error {
return nil
return nil
}
// OnFree gets called at some time after a reload.
@@ -76,22 +76,22 @@ func OnFree() {
// Export returns an object to be exported to other plugins.
func Export() interface{} {
return nil
return nil
}
// Import returns an object indicating the dependencies of the plugin.
func Import() interface{} {
return nil
return nil
}
// InvokeFunc invokes the specified function.
func InvokeFunc(name string, params ...interface{}) (interface{}, error) {
return nil, nil
return nil, nil
}
// Reloadable indicates whether the plugin is reloadable.
func Reloadable() bool {
return true
return true
}
```

View File

@@ -60,12 +60,12 @@ Flags:
// OnLoad gets called after all plugins are successfully loaded and all dependencies are
// properly initialized.
func OnLoad(data interface{}) error {
return nil
return nil
}
// OnInit gets called after the execution of all OnLoad functions.
func OnInit(sharedVault *vault.Vault) error {
return nil
return nil
}
// OnFree gets called at some time after a reload.
@@ -74,22 +74,22 @@ func OnFree() {
// Export returns an object to be exported to other plugins.
func Export() interface{} {
return nil
return nil
}
// Import returns an object indicating the dependencies of the plugin.
func Import() interface{} {
return nil
return nil
}
// InvokeFunc invokes the specified function.
func InvokeFunc(name string, params ...interface{}) (interface{}, error) {
return nil, nil
return nil, nil
}
// Reloadable indicates whether the plugin is reloadable.
func Reloadable() bool {
return true
return true
}
```

View File

@@ -273,7 +273,7 @@ next1:
}()
defer func() {
select {
case chSignal <- syscall.SIGUSR1:
case chSignal <- syscall.SIGQUIT:
default:
}
<-done
@@ -281,6 +281,10 @@ next1:
var outputFile string
if !wo.staticLinking {
if runtime.GOOS == "windows" {
_, _ = os.Stderr.WriteString("Go plugin does not support Windows at present. Use --staticLinking if you only want to debug.\n")
os.Exit(1)
}
if os.Getenv("hotswap:checkRequiredPluginFuncs") != "1" {
parseRequiredPluginFuncs(wo.pluginDir, "")
}

View File

@@ -44,4 +44,4 @@ plugin/dog/build.sh
echo
echo "Sending signal..."
kill -USR1 `cat "bin/$xOS/$PROGRAM.pid"`
touch "bin/$xOS/$PROGRAM.reload"

View File

@@ -69,4 +69,4 @@ if [[ $REPLY =~ ^[Nn]$ ]]; then
fi
printf "Starting $PROGRAM...\n\n"
"$PROGRAM_EXE" --pluginDir="bin/$xOS/plugin/$PROGRAM" --pidFile="bin/$xOS/$PROGRAM.pid" "$staticLinking"
"$PROGRAM_EXE" --pluginDir="bin/$xOS/plugin/$PROGRAM" --pidFile="bin/$xOS/$PROGRAM.pid" --signalFile="bin/$xOS/$PROGRAM.reload" "$staticLinking"

View File

@@ -26,9 +26,11 @@ func init() {
func main() {
var pluginDir string
var pidFile string
var signalFile string
var staticLinking bool
flag.StringVar(&pluginDir, "pluginDir", "", "the directory holding your plugins")
flag.StringVar(&pidFile, "pidFile", "", "pid file path")
flag.StringVar(&signalFile, "signalFile", "", "once the specified file is found on your disk, reload all plugins")
flag.BoolVar(&staticLinking, "staticLinking", false, "link plugin statically (not reloadable)")
flag.Parse()
@@ -42,6 +44,9 @@ func main() {
if pidFile == "" {
panic("no --pidFile")
}
if signalFile == "" {
panic("no --signalFile")
}
pid := fmt.Sprint(os.Getpid())
if err := ioutil.WriteFile(pidFile, []byte(pid), 0644); err != nil {
@@ -74,9 +79,40 @@ func main() {
}
}()
go func() {
for range time.Tick(time.Millisecond * 50) {
if _, err := os.Stat(signalFile); err != nil {
continue
}
g.Logger.Info("<hotswap> reloading...")
details, err := swapper.Reload(nil)
if staticLinking {
if err != nil {
g.Logger.Errorf("<hotswap> %s", err)
break
}
panic("impossible")
}
if err != nil {
panic(err)
} else if len(details) == 0 {
g.Logger.Infof("no plugin is found in " + absDir)
} else {
g.Logger.Infof("<hotswap> %d plugin(s) loaded. details: [%s]",
len(details), details)
}
heartbeat()
if err := os.Remove(signalFile); err != nil {
g.Logger.Error(err)
os.Exit(1)
}
}
}()
// Wait for signals
chSignal := make(chan os.Signal, 1)
signal.Notify(chSignal, syscall.SIGINT, syscall.SIGTERM, syscall.SIGUSR1)
signal.Notify(chSignal, syscall.SIGINT, syscall.SIGTERM)
loop:
for {
@@ -86,30 +122,11 @@ loop:
switch sig {
case syscall.SIGINT, syscall.SIGTERM:
break loop
case syscall.SIGUSR1:
g.Logger.Info("<hotswap> reloading...")
details, err := swapper.Reload(nil)
if staticLinking {
if err != nil {
g.Logger.Errorf("<hotswap> %s", err)
break
}
panic("impossible")
}
if err != nil {
panic(err)
} else if len(details) == 0 {
g.Logger.Infof("no plugin is found in " + absDir)
} else {
g.Logger.Infof("<hotswap> %d plugin(s) loaded. details: [%s]",
len(details), details)
}
heartbeat()
}
}
}
signal.Reset(syscall.SIGINT, syscall.SIGTERM, syscall.SIGUSR1)
signal.Reset(syscall.SIGINT, syscall.SIGTERM)
g.Logger.Info("THE END")
}