summaryrefslogtreecommitdiffstats
path: root/plugin/rpcplugin/supervisor.go
diff options
context:
space:
mode:
authorJesse Hallam <jesse.hallam@gmail.com>2018-05-23 14:26:35 -0400
committerGitHub <noreply@github.com>2018-05-23 14:26:35 -0400
commit847c181ec9b73e51daf39efc5c597eff2e7cdb31 (patch)
tree54bcb4a3ac43f9acb22ff037582541c7428bd990 /plugin/rpcplugin/supervisor.go
parent5c21bdc1783e5cd17169436e7ccfacdd1b637907 (diff)
downloadchat-847c181ec9b73e51daf39efc5c597eff2e7cdb31.tar.gz
chat-847c181ec9b73e51daf39efc5c597eff2e7cdb31.tar.bz2
chat-847c181ec9b73e51daf39efc5c597eff2e7cdb31.zip
MM-8622: Improved plugin error reporting (#8737)
* allow `Wait()`ing on the supervisor In the event the plugin supervisor shuts down a plugin for crashing too many times, the new `Wait()` interface allows the `ActivatePlugin` to accept a callback function to trigger when `supervisor.Wait()` returns. If the supervisor shuts down normally, this callback is invoked with a nil error, otherwise any error reported by the supervisor is passed along. * improve plugin activation/deactivation logic Avoid triggering activation of previously failed-to-start plugins just becase something in the configuration changed. Now, intelligently compare the global enable bit as well as the each individual plugin's enabled bit. * expose store to manipulate PluginStatuses * expose API to fetch plugin statuses * keep track of whether or not plugin sandboxing is supported * transition plugin statuses * restore error on plugin activation if already active * don't initialize test plugins until successfully loaded * emit websocket events when plugin statuses change * skip pruning if already initialized * MM-8622: maintain plugin statuses in memory Switch away from persisting plugin statuses to the database, and maintain in memory instead. This will be followed by a cluster interface to query the in-memory status of plugin statuses from all cluster nodes. At the same time, rename `cluster_discovery_id` on the `PluginStatus` model object to `cluster_id`. * MM-8622: aggregate plugin statuses across cluster * fetch cluster plugin statuses when emitting websocket notification * address unit test fixes after rebasing * relax (poor) racey unit test re: supervisor.Wait() * make store-mocks
Diffstat (limited to 'plugin/rpcplugin/supervisor.go')
-rw-r--r--plugin/rpcplugin/supervisor.go15
1 files changed, 12 insertions, 3 deletions
diff --git a/plugin/rpcplugin/supervisor.go b/plugin/rpcplugin/supervisor.go
index 6e26d5682..246747c89 100644
--- a/plugin/rpcplugin/supervisor.go
+++ b/plugin/rpcplugin/supervisor.go
@@ -32,6 +32,7 @@ type Supervisor struct {
cancel context.CancelFunc
newProcess func(context.Context) (Process, io.ReadWriteCloser, error)
pluginId string
+ pluginErr error
}
var _ plugin.Supervisor = (*Supervisor)(nil)
@@ -55,6 +56,13 @@ func (s *Supervisor) Start(api plugin.API) error {
}
}
+// Waits for the supervisor to stop (on demand or of its own accord), returning any error that
+// triggered the supervisor to stop.
+func (s *Supervisor) Wait() error {
+ <-s.done
+ return s.pluginErr
+}
+
// Stops the plugin.
func (s *Supervisor) Stop() error {
s.cancel()
@@ -70,7 +78,7 @@ func (s *Supervisor) Hooks() plugin.Hooks {
func (s *Supervisor) run(ctx context.Context, start chan<- error, api plugin.API) {
defer func() {
- s.done <- true
+ close(s.done)
}()
done := ctx.Done()
for i := 0; i <= MaxProcessRestarts; i++ {
@@ -81,10 +89,11 @@ func (s *Supervisor) run(ctx context.Context, start chan<- error, api plugin.API
default:
start = nil
if i < MaxProcessRestarts {
- mlog.Debug("Plugin terminated unexpectedly", mlog.String("plugin_id", s.pluginId))
+ mlog.Error("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))
+ s.pluginErr = fmt.Errorf("plugin terminated unexpectedly too many times")
+ mlog.Error("Plugin shutdown", mlog.String("plugin_id", s.pluginId), mlog.Int("max_process_restarts", MaxProcessRestarts), mlog.Err(s.pluginErr))
}
}
}