Skip to content

Commit

Permalink
start catching panics
Browse files Browse the repository at this point in the history
  • Loading branch information
vizicist committed Dec 12, 2023
1 parent b9a9113 commit 0ff094b
Show file tree
Hide file tree
Showing 16 changed files with 173 additions and 35 deletions.
15 changes: 15 additions & 0 deletions cmd/palette/palette.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,21 @@ func CliCommand(args []string) (map[string]string, error) {
out := map[string]string{"result": s}
return out, nil

case "restart":
_, err := CliCommand([]string{"stop"})
if err != nil {
return nil, err
}
_, err = CliCommand([]string{"start"})
if err != nil {
return nil, err
}
out := map[string]string{"result": "RESTARTED"}
return out, nil

// case "api":
// return kit.EngineApi(arg1, args[2:])

case "start":

switch arg1 {
Expand Down
14 changes: 14 additions & 0 deletions cmd/palette_engine/palette_engine.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package main

import (
"fmt"
"os"
"os/signal"
"runtime/debug"
"runtime/pprof"
"syscall"

Expand All @@ -29,6 +31,18 @@ func main() {
signal.Ignore(syscall.SIGINT)

kit.InitLog("engine")

defer func() {
if r := recover(); r != nil {
// Print stack trace in the error messages
stacktrace := string(debug.Stack())
// First to stdout, then to log file
fmt.Printf("PANIC: recover in palette_engine called, r=%+v stack=%v", r, stacktrace)
err := fmt.Errorf("PANIC: recover in palette_engine has been called")
kit.LogError(err, "r", r, "stack", stacktrace)
}
}()

kit.InitMisc()
kit.InitEngine()

Expand Down
4 changes: 2 additions & 2 deletions data/config/paramdefs.json
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@
"global.midithru": {"valuetype":"bool", "min":"false", "max":"true", "init":"false", "comment":"#" },
"global.midithrusynth": {"valuetype":"string", "min":"synth", "max":"synth", "init":"default", "comment":"#" },
"global.midisetexternalscale": {"valuetype":"bool", "min":"false", "max":"true", "init":"false", "comment":"#" },
"global.morphtype": {"valuetype":"string", "min":"morphtype", "max":"morphtype", "init":"quadrants", "comment":"#" },
"global.morphdefault": {"valuetype":"string", "min":"morphtype", "max":"morphtype", "init":"quadrants", "comment":"#" },
"global.mmtt_xexpand": {"valuetype": "float", "min": "0.5", "max": "2.0", "init": "1.25", "comment": "#" },
"global.mmtt_yexpand": {"valuetype": "float", "min": "0.5", "max": "2.0", "init": "1.25", "comment": "#" },
"global.mmtt_zexpand": {"valuetype": "float", "min": "0.5", "max": "10.0", "init": "4.0", "comment": "#" },
Expand All @@ -208,7 +208,7 @@
"global.process.resolume": {"valuetype":"bool", "min":"false", "max":"true", "init":"true", "comment":"#" },
"global.process.mmtt": {"valuetype":"bool", "min":"false", "max":"true", "init":"false", "comment":"#" },
"global.process.obs": {"valuetype":"bool", "min":"false", "max":"true", "init":"false", "comment":"#" },
"global.resolumepath": {"valuetype":"string", "min":"", "max":"", "init":"C:/Program Files/Resolume Avenue/Avenue.exe", "comment":"# Resolume executable path" },
"global.resolumepath": {"valuetype":"string", "min":"resolumepath", "max":"resolumepath", "init":"C:/Program Files/Resolume Avenue/Avenue.exe", "comment":"# Resolume executable path" },
"global.resolumetextlayer": {"valuetype":"int", "min":"1", "max":"10", "init":"5", "comment":"# text layer num" },
"global.scale": {"valuetype":"string", "min":"enginescale", "max":"enginescale", "init":"", "comment":"# " },
"global.tempdir": {"valuetype":"string", "min":"", "max":"", "init":"C:/windows/temp", "comment":"# " },
Expand Down
1 change: 1 addition & 0 deletions data/config/paramenums.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"resolumepath": ["C:/Program Files/Resolume Avenue/Avenue.exe", "C:/Program Files/Resolume Arena/Arena.exe"],
"plugins": [ "", "quadpro" ],
"log": ["","cursor","midi","cursor,midi","cursor,midi,osc","osc","api","loop", "morph","mmtt", "quant", "transpose", "ffgl", "gesture"],
"pitchset": ["","stylusrmx"],
Expand Down
20 changes: 17 additions & 3 deletions kit/bidule.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"path/filepath"
"sync"
"time"
"runtime/debug"
"fmt"

"github.com/hypebeast/go-osc/osc"
)
Expand Down Expand Up @@ -43,25 +45,37 @@ func (b *Bidule) ProcessInfo() *ProcessInfo {
bidulePath, err := GetParam("global.bidulepath")
if err != nil {
LogIfError(err)
return nil
return EmptyProcessInfo()
}
if !FileExists(bidulePath) {
LogWarn("No bidule found, looking for", "path", bidulePath)
return nil
return EmptyProcessInfo()
}
exe := filepath.Base(bidulePath)

bidulefile, err := GetParam("global.bidulefile")
if err != nil {
LogIfError(err)
return nil
return EmptyProcessInfo()
}
filepath := ConfigFilePath(bidulefile)
return NewProcessInfo(exe, bidulePath, filepath, b.Activate)
}

func (b *Bidule) Reset() {

defer func() {
if r := recover(); r != nil {
// Print stack trace in the error messages
stacktrace := string(debug.Stack())
// First to stdout, then to log file
fmt.Printf("PANIC: recover in Bidule.Reset called, r=%+v stack=%v", r, stacktrace)
err := fmt.Errorf("PANIC: recover in Bidule.Reset has been called")
LogError(err, "r", r, "stack", stacktrace)
}
}()


b.mutex.Lock()
defer b.mutex.Unlock()

Expand Down
24 changes: 24 additions & 0 deletions kit/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"net/http"
"os"
"path/filepath"
"runtime/debug"
"strconv"
"sync"
"sync/atomic"
Expand Down Expand Up @@ -195,6 +196,7 @@ func LoadGlobalParams() (err error) {
func (e *Engine) Start() {

e.done = make(chan bool)

LogInfo("Engine.Start")

InitMidiIO()
Expand Down Expand Up @@ -249,6 +251,17 @@ func (e *Engine) sendToOscClients(msg *osc.Message) {

func (e *Engine) StartOscListener(port int) {

defer func() {
if r := recover(); r != nil {
// Print stack trace in the error messages
stacktrace := string(debug.Stack())
// First to stdout, then to log file
fmt.Printf("PANIC: recover in StartOscListener called, r=%+v stack=%v", r, stacktrace)
err := fmt.Errorf("PANIC: recover in StartOscListener has been called")
LogError(err, "r", r, "stack", stacktrace)
}
}()

source := fmt.Sprintf("%s:%d", LocalAddress, port)

d := osc.NewStandardDispatcher()
Expand All @@ -273,6 +286,17 @@ func (e *Engine) StartOscListener(port int) {
// StartHttp xxx
func (e *Engine) StartHttp(port int) {

defer func() {
if r := recover(); r != nil {
// Print stack trace in the error messages
stacktrace := string(debug.Stack())
// First to stdout, then to log file
fmt.Printf("PANIC: recover in StartHttp called, r=%+v stack=%v", r, stacktrace)
err := fmt.Errorf("PANIC: recover in StartHttp has been called")
LogError(err, "r", r, "stack", stacktrace)
}
}()

http.HandleFunc("/api", func(responseWriter http.ResponseWriter, req *http.Request) {

responseWriter.Header().Set("Content-Type", "application/json")
Expand Down
19 changes: 19 additions & 0 deletions kit/engineapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"strconv"
"strings"
"time"
"runtime/debug"
)

// ExecuteApi xxx
Expand Down Expand Up @@ -47,8 +48,21 @@ func ExecuteApi(api string, apiargs map[string]string) (result string, err error
// unreachable
}


// ExecuteApiFromJson takes raw JSON (as a string of the form "{...}"") as an API and returns raw JSON
func ExecuteApiFromJson(rawjson string) (string, error) {

defer func() {
if r := recover(); r != nil {
// Print stack trace in the error messages
stacktrace := string(debug.Stack())
// First to stdout, then to log file
fmt.Printf("PANIC: recover in ExecuteApiFromJson called, r=%+v stack=%v", r, stacktrace)
err := fmt.Errorf("PANIC: recover in ExecuteApiFromJson has been called")
LogError(err, "r", r, "stack", stacktrace)
}
}()

args, err := StringMap(rawjson)
if err != nil {
return "", fmt.Errorf("Router.ExecuteApiAsJson: bad format of JSON")
Expand All @@ -64,6 +78,11 @@ func ExecuteGlobalApi(api string, apiargs map[string]string) (result string, err

switch api {

case "debugnil":
// Generate a nil pointer panic
var a *Engine
a.SayDone()

case "debugsched":
return TheScheduler.ToString(), nil

Expand Down
13 changes: 8 additions & 5 deletions kit/log.go
Original file line number Diff line number Diff line change
Expand Up @@ -257,12 +257,11 @@ func LogError(err error, keysAndValues ...any) {
}

if (len(keysAndValues) % 2) != 0 {
LogWarn("LogIfError function given bad number of arguments")
LogWarn("LogError function given bad number of arguments")
}
keysAndValues = append(keysAndValues, "err")
keysAndValues = append(keysAndValues, err)
caller := "LogIfError"
LogWarn(caller, keysAndValues...)
LogRaw("error", "LogError", keysAndValues...)
}

func appendExtraValues(keysAndValues []any) []any {
Expand Down Expand Up @@ -291,12 +290,16 @@ func LogOfType(logtypes string, msg string, keysAndValues ...any) {
}

func LogWarn(msg string, keysAndValues ...any) {
LogRaw("warn", msg, keysAndValues...)
}

func LogRaw(loglevel string, msg string, keysAndValues ...any) {
if (len(keysAndValues) % 2) != 0 {
LogWarn("Warn function given bad number of arguments")
LogWarn("LogRaw function given bad number of arguments","msg",msg)
} else {
keysAndValues = appendExtraValues(keysAndValues)
keysAndValues = append(keysAndValues, "loglevel")
keysAndValues = append(keysAndValues, "warn")
keysAndValues = append(keysAndValues, loglevel)
TheLog.Warnw(msg, keysAndValues...)
}
}
Expand Down
12 changes: 12 additions & 0 deletions kit/midiio.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"fmt"
"strings"
"sync"
"runtime/debug"

midi "gitlab.com/gomidi/midi/v2"
"gitlab.com/gomidi/midi/v2/drivers"
Expand Down Expand Up @@ -128,6 +129,17 @@ func (m *MidiIO) handleMidiError(err error) {

func (m *MidiIO) Start() {

defer func() {
if r := recover(); r != nil {
// Print stack trace in the error messages
stacktrace := string(debug.Stack())
// First to stdout, then to log file
fmt.Printf("PANIC: recover in MidiIO.Start called, r=%+v stack=%v", r, stacktrace)
err := fmt.Errorf("PANIC: recover in MidiIO.Start has been called")
LogError(err, "r", r, "stack", stacktrace)
}
}()

if m.midiInput == nil {
LogWarn("No MIDI input port has been selected")
return
Expand Down
1 change: 1 addition & 0 deletions kit/misc.go
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,7 @@ func (w *FileWriter) Write(p []byte) (n int, err error) {
strings.Contains(s, "Logging output channels") ||
strings.Contains(s, "Logging midi input devices") ||
strings.Contains(s, "Internal MIDI") ||
strings.Contains(s, "Sensel MIDI") ||
strings.Contains(s, "Could not find preset") ) {
// don't log it
} else {
Expand Down
2 changes: 1 addition & 1 deletion kit/obs.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ func ObsProcessInfo() *ProcessInfo {
LogIfError(err)
if fullpath != "" && !FileExists(fullpath) {
LogWarn("No OBS found, looking for", "path", fullpath)
return nil
return EmptyProcessInfo()
}
exe := filepath.Base(fullpath)
pi := NewProcessInfo(exe, fullpath, "", ObsActivate)
Expand Down
35 changes: 15 additions & 20 deletions kit/process.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ func NewProcessInfo(exe, fullPath, arg string, activate func()) *ProcessInfo {
}
}

func EmptyProcessInfo() *ProcessInfo {
return NewProcessInfo("", "", "", nil)
}

func StartRunning(process string) error {
err := TheProcessManager.StartRunning(process)
if err != nil {
Expand Down Expand Up @@ -172,18 +176,14 @@ func ProcessList() []string {
arr = append(arr, "resolume")
arr = append(arr, "obs")
arr = append(arr, "chat")
arr = append(arr, "mmtt")
/*
keykit, err := GetParamBool("global.keykitrun")
LogIfError(err)
if keykit {
arr = append(arr, "keykit")
}
*/
mmtt, err := GetParam("global.mmtt")
LogIfError(err)
if mmtt != "" {
arr = append(arr, "mmtt")
}
return arr
}

Expand Down Expand Up @@ -331,12 +331,12 @@ func GuiProcessInfo() *ProcessInfo {
gui, err := GetParam("global.gui")
if err != nil {
LogIfError(err)
return nil
return EmptyProcessInfo()
}
fullpath := filepath.Join(PaletteDir(), gui)
if fullpath != "" && !FileExists(fullpath) {
LogWarn("No Gui found, looking for", "path", fullpath)
return nil
return EmptyProcessInfo()
}
exe := filepath.Base(fullpath)

Expand All @@ -355,7 +355,7 @@ func ChatProcessInfo() *ProcessInfo {
fullpath := filepath.Join(paletteRoot, "bin", "palette_chat.exe")
if fullpath != "" && !FileExists(fullpath) {
LogWarn("No chat executable found, looking for", "path", fullpath)
return nil
return EmptyProcessInfo()
}
exe := filepath.Base(fullpath)
return NewProcessInfo(exe, fullpath, "", nil)
Expand Down Expand Up @@ -406,7 +406,7 @@ func KeykitProcessInfo() *ProcessInfo {
fullpath = filepath.Join(PaletteDir(), "keykit", "bin", KeykitExe)
if !FileExists(fullpath) {
LogWarn("Keykit not found in default location", "fullpath", fullpath)
return nil
return EmptyProcessInfo()
}
}
exe := filepath.Base(fullpath)
Expand All @@ -416,22 +416,17 @@ func KeykitProcessInfo() *ProcessInfo {

func MmttProcessInfo() *ProcessInfo {

/*
// The value of mmtt is either "kinect" or "oak" or ""
mmtt, err := GetParam("global.mmtt")
LogIfError(err)
if mmtt == "" {
return nil
}
*/
// The value of PALETTE_MMTT environment variable can be "kinect" or (someday) "oak"
mmtt := os.Getenv("PALETTE_MMTT")
if mmtt == "" {
return nil
// This warning would be annoying, since PALETTE_MMTT rarely set
// LogInfo("No PALETTE_MMTT environment variable set")
return EmptyProcessInfo()
}
fullpath := filepath.Join(PaletteDir(), "bin", "mmtt_"+mmtt, "mmtt_"+mmtt+".exe")
if !FileExists(fullpath) {
LogWarn(" executable found, looking for", "fullpath", fullpath)
fullpath = ""
LogWarn("mmtt executable not found, looking for", "fullpath", fullpath)
return EmptyProcessInfo()
}
return NewProcessInfo("mmtt_"+mmtt+".exe", fullpath, "", nil)
}
Loading

0 comments on commit 0ff094b

Please sign in to comment.