From 43820cd9f0331e4212769876d186348bd5153c43 Mon Sep 17 00:00:00 2001 From: Nicolas Carlier Date: Wed, 21 Mar 2018 14:09:19 +0000 Subject: [PATCH] fix(): fix panic due to writing into closed chan --- pkg/api/api.go | 11 +++-------- pkg/worker/script_runner.go | 6 +++++- pkg/worker/work_request.go | 14 ++++++++++++++ pkg/worker/worker.go | 3 ++- 4 files changed, 24 insertions(+), 10 deletions(-) diff --git a/pkg/api/api.go b/pkg/api/api.go index 6b59228..2a6747d 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -64,13 +64,8 @@ func webhookHandler(w http.ResponseWriter, r *http.Request) { params = append(params, tools.HTTPHeadersToShellVars(r.Header)...) // Create work - work := new(worker.WorkRequest) - work.Name = p - work.Script = script - work.Payload = string(body) - work.Args = params - work.MessageChan = make(chan []byte) - work.Timeout = atoiFallback(r.Header.Get("X-Hook-Timeout"), defaultTimeout) + timeout := atoiFallback(r.Header.Get("X-Hook-Timeout"), defaultTimeout) + work := worker.NewWorkRequest(p, script, string(body), params, timeout) // Put work in queue worker.WorkQueue <- *work @@ -81,7 +76,7 @@ func webhookHandler(w http.ResponseWriter, r *http.Request) { w.Header().Set("Access-Control-Allow-Origin", "*") logger.Debug.Println("Work request queued:", script) - fmt.Fprintf(w, "data: Hook work request \"%s\" queued...\n\n", work.Name) + // fmt.Fprintf(w, "data: Running \"%s\" ...\n\n", work.Name) for { msg, open := <-work.MessageChan diff --git a/pkg/worker/script_runner.go b/pkg/worker/script_runner.go index 80bf2f5..7637fde 100644 --- a/pkg/worker/script_runner.go +++ b/pkg/worker/script_runner.go @@ -68,6 +68,10 @@ func runScript(work *WorkRequest) (string, error) { go func(reader io.Reader) { scanner := bufio.NewScanner(reader) for scanner.Scan() { + if work.Closed { + logger.Error.Println("Unable to write into the work channel. Work request closed.") + return + } // writing to the work channel line := scanner.Text() work.MessageChan <- []byte(line) @@ -95,6 +99,6 @@ func runScript(work *WorkRequest) (string, error) { return logFilename, err } timer.Stop() - logger.Info.Println("Script", work.Script, "executed wit SUCCESS") + logger.Info.Println("Script", work.Script, "executed with SUCCESS") return logFilename, nil } diff --git a/pkg/worker/work_request.go b/pkg/worker/work_request.go index 6c8513e..2b13696 100644 --- a/pkg/worker/work_request.go +++ b/pkg/worker/work_request.go @@ -8,4 +8,18 @@ type WorkRequest struct { Args []string MessageChan chan []byte Timeout int + Closed bool +} + +// NewWorkRequest creats new work request +func NewWorkRequest(name, script, payload string, args []string, timeout int) *WorkRequest { + return &WorkRequest{ + Name: name, + Script: script, + Payload: payload, + Args: args, + Timeout: timeout, + MessageChan: make(chan []byte), + Closed: false, + } } diff --git a/pkg/worker/worker.go b/pkg/worker/worker.go index d4264a3..b27e15b 100644 --- a/pkg/worker/worker.go +++ b/pkg/worker/worker.go @@ -52,6 +52,7 @@ func (w Worker) Start() { work.MessageChan <- []byte("done") notify(subject, "See attachment.", filename) } + work.Closed = true close(work.MessageChan) case <-w.QuitChan: logger.Debug.Printf("Stopping worker%d...\n", w.ID) @@ -72,7 +73,7 @@ func (w Worker) Stop() { func notify(subject string, text string, outfilename string) { var notifier, err = notification.NotifierFactory() if err != nil { - logger.Info.Println("Unable to get the notifier. Notification skipped:", err) + logger.Debug.Println("Unable to get the notifier. Notification skipped:", err) return } if notifier == nil {