summaryrefslogtreecommitdiffstats
path: root/plugin/rpcplugin/supervisor.go
diff options
context:
space:
mode:
Diffstat (limited to 'plugin/rpcplugin/supervisor.go')
-rw-r--r--plugin/rpcplugin/supervisor.go26
1 files changed, 21 insertions, 5 deletions
diff --git a/plugin/rpcplugin/supervisor.go b/plugin/rpcplugin/supervisor.go
index 6a48cb5e8..6e26d5682 100644
--- a/plugin/rpcplugin/supervisor.go
+++ b/plugin/rpcplugin/supervisor.go
@@ -12,19 +12,26 @@ import (
"sync/atomic"
"time"
+ "github.com/mattermost/mattermost-server/mlog"
"github.com/mattermost/mattermost-server/model"
"github.com/mattermost/mattermost-server/plugin"
)
+const (
+ MaxProcessRestarts = 3
+)
+
// Supervisor implements a plugin.Supervisor that launches the plugin in a separate process and
// communicates via RPC.
//
-// If the plugin unexpectedly exists, the supervisor will relaunch it after a short delay.
+// If the plugin unexpectedly exits, the supervisor will relaunch it after a short delay, but will
+// only restart a plugin at most three times.
type Supervisor struct {
hooks atomic.Value
done chan bool
cancel context.CancelFunc
newProcess func(context.Context) (Process, io.ReadWriteCloser, error)
+ pluginId string
}
var _ plugin.Supervisor = (*Supervisor)(nil)
@@ -66,19 +73,28 @@ func (s *Supervisor) run(ctx context.Context, start chan<- error, api plugin.API
s.done <- true
}()
done := ctx.Done()
- for {
+ for i := 0; i <= MaxProcessRestarts; i++ {
s.runPlugin(ctx, start, api)
select {
case <-done:
return
default:
start = nil
- time.Sleep(time.Second)
+ if i < MaxProcessRestarts {
+ mlog.Debug("Plugin terminated unexpectedly", mlog.String("plugin_id", s.pluginId))
+ time.Sleep(time.Duration((1 + i*i)) * time.Second)
+ } else {
+ mlog.Debug("Plugin terminated unexpectedly too many times", mlog.String("plugin_id", s.pluginId), mlog.Int("max_process_restarts", MaxProcessRestarts))
+ }
}
}
}
func (s *Supervisor) runPlugin(ctx context.Context, start chan<- error, api plugin.API) error {
+ if start == nil {
+ mlog.Debug("Restarting plugin", mlog.String("plugin_id", s.pluginId))
+ }
+
p, ipc, err := s.newProcess(ctx)
if err != nil {
if start != nil {
@@ -100,7 +116,7 @@ func (s *Supervisor) runPlugin(ctx context.Context, start chan<- error, api plug
muxerClosed <- muxer.Close()
}()
- hooks, err := ConnectMain(muxer)
+ hooks, err := ConnectMain(muxer, s.pluginId)
if err == nil {
err = hooks.OnActivate(api)
}
@@ -147,5 +163,5 @@ func SupervisorWithNewProcessFunc(bundle *model.BundleInfo, newProcess func(cont
if strings.HasPrefix(executable, "..") {
return nil, fmt.Errorf("invalid backend executable")
}
- return &Supervisor{newProcess: newProcess}, nil
+ return &Supervisor{pluginId: bundle.Manifest.Id, newProcess: newProcess}, nil
}