diff options
Diffstat (limited to 'plugin/rpcplugin/supervisor.go')
-rw-r--r-- | plugin/rpcplugin/supervisor.go | 26 |
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 } |