From f0b2488a1f1dd98c59a382635158f19a6302b21c Mon Sep 17 00:00:00 2001 From: Arek Ouzounian Date: Mon, 24 Jun 2024 14:04:17 -0700 Subject: [PATCH 1/6] propagating compiler errors --- engine/controller/controller.go | 4 ++-- engine/process/main.go | 6 +++++- web-frontend/js/config-utils.js | 4 ++-- web-frontend/js/run-request.js | 2 ++ 4 files changed, 11 insertions(+), 5 deletions(-) diff --git a/engine/controller/controller.go b/engine/controller/controller.go index 76e97b6..d8acb95 100644 --- a/engine/controller/controller.go +++ b/engine/controller/controller.go @@ -102,11 +102,11 @@ func (ac *AsyncController) SubmitRequest(runprops *Props) *CtrlRunOutput { if runprops.PreRunProps != nil { preRunOut, commandErr := agent.SafeRunCmd(preRunProps) - print2.DebugPrintf("error preparing command: output=%v\n \nerror=%v", preRunOut, commandErr) if commandErr != nil { + print2.DebugPrintf("error preparing command: output=%v\n \nerror=%v", preRunOut, commandErr) return &CtrlRunOutput{ ControllerErr: PreRunError, - RunOutput: nil, + RunOutput: preRunOut, CommandErr: nil, } } diff --git a/engine/process/main.go b/engine/process/main.go index aab038c..470d8df 100644 --- a/engine/process/main.go +++ b/engine/process/main.go @@ -98,10 +98,14 @@ func main() { cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr + err = cmd.Run() if err != nil { print.ProcDebug("error running process: %v\n", err) - os.Exit(ERunningProc) + // os.Exit(ERunningProc) + if cast, ok := err.(*exec.ExitError); ok { + os.Exit(cast.ExitCode()) + } } } diff --git a/web-frontend/js/config-utils.js b/web-frontend/js/config-utils.js index 0316c03..9f3b2be 100644 --- a/web-frontend/js/config-utils.js +++ b/web-frontend/js/config-utils.js @@ -6,8 +6,8 @@ function getSelectedLanguage() { const runnerConfig = { getSelectedLanguage: getSelectedLanguage, // Uncomment for local testing - // url: "http://localhost:10100/api/v1/", - url: "https://runner.fly.dev/api/v1/", + url: "http://localhost:10100/api/v1/", + // url: "https://runner.fly.dev/api/v1/", runEndpoint: "run", langEndpoint: "languages", }; diff --git a/web-frontend/js/run-request.js b/web-frontend/js/run-request.js index d81c50d..e7fc0de 100644 --- a/web-frontend/js/run-request.js +++ b/web-frontend/js/run-request.js @@ -19,6 +19,7 @@ function runRequest() { reject({ status: this.status, statusText: xhr.statusText, + body: xhr.response }); } }; @@ -26,6 +27,7 @@ function runRequest() { reject({ status: this.status, statusText: xhr.statusText, + body: xhr.response }); }; xhr.send(JSON.stringify(req)); From 5195b43097c8d74d09d756a5f4b3e5a5bba629e2 Mon Sep 17 00:00:00 2001 From: Arek Ouzounian Date: Mon, 24 Jun 2024 14:10:46 -0700 Subject: [PATCH 2/6] fixing mistake with localhost requests --- web-frontend/js/config-utils.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web-frontend/js/config-utils.js b/web-frontend/js/config-utils.js index 9f3b2be..0316c03 100644 --- a/web-frontend/js/config-utils.js +++ b/web-frontend/js/config-utils.js @@ -6,8 +6,8 @@ function getSelectedLanguage() { const runnerConfig = { getSelectedLanguage: getSelectedLanguage, // Uncomment for local testing - url: "http://localhost:10100/api/v1/", - // url: "https://runner.fly.dev/api/v1/", + // url: "http://localhost:10100/api/v1/", + url: "https://runner.fly.dev/api/v1/", runEndpoint: "run", langEndpoint: "languages", }; From 7d58b16499d6beb826aaaf166f0fe3fbb316623f Mon Sep 17 00:00:00 2001 From: Arek Ouzounian Date: Mon, 24 Jun 2024 15:46:29 -0700 Subject: [PATCH 3/6] runtime errors also propagating --- engine/controller/controller.go | 4 ++-- engine/process/main.go | 13 ++++++++++++- server/api/v2/types.go | 2 +- server/main.go | 5 ++++- web-frontend/js/run-request.js | 9 ++++----- web-frontend/style/main.css | 8 ++++++-- 6 files changed, 29 insertions(+), 12 deletions(-) diff --git a/engine/controller/controller.go b/engine/controller/controller.go index d8acb95..73adeee 100644 --- a/engine/controller/controller.go +++ b/engine/controller/controller.go @@ -105,9 +105,9 @@ func (ac *AsyncController) SubmitRequest(runprops *Props) *CtrlRunOutput { if commandErr != nil { print2.DebugPrintf("error preparing command: output=%v\n \nerror=%v", preRunOut, commandErr) return &CtrlRunOutput{ - ControllerErr: PreRunError, + ControllerErr: nil, RunOutput: preRunOut, - CommandErr: nil, + CommandErr: commandErr, } } } diff --git a/engine/process/main.go b/engine/process/main.go index 470d8df..5fe328b 100644 --- a/engine/process/main.go +++ b/engine/process/main.go @@ -103,8 +103,19 @@ func main() { if err != nil { print.ProcDebug("error running process: %v\n", err) - // os.Exit(ERunningProc) if cast, ok := err.(*exec.ExitError); ok { + if ws, ok := cast.Sys().(syscall.WaitStatus); ok { + if ws.Signaled() { + // more verbose err message + cmd.Stderr.Write([]byte(err.Error())) + + // signal exit code: 128 + signal code + os.Exit(128 + int(ws.Signal())) + } + } + + // if for some reason we can't get the wait status then we + // can just get the (probably incorrect) error code from the cast os.Exit(cast.ExitCode()) } } diff --git a/server/api/v2/types.go b/server/api/v2/types.go index fdf4bf6..1f8c6d4 100644 --- a/server/api/v2/types.go +++ b/server/api/v2/types.go @@ -22,5 +22,5 @@ type RunResponse struct { // Stderr is standard error stream from running program Stderr string `json:"stderr"` // Error result from either compilation or runtime errors. Will be nil if both compilation and runtime were successful. - Error error `json:"error"` + Error string `json:"error"` } diff --git a/server/main.go b/server/main.go index eee77ce..d0d9e18 100644 --- a/server/main.go +++ b/server/main.go @@ -84,7 +84,10 @@ func (rs RunnerServer) runHandler(w http.ResponseWriter, r *http.Request) { output := api.RunResponse{ Stdout: RunnerOutput.Stdout, Stderr: RunnerOutput.Stderr, - Error: RunnerOutput.CommandError, + // Error: RunnerOutput.CommandError.Error(), + } + if RunnerOutput.CommandError != nil { + output.Error = RunnerOutput.CommandError.Error() } err = json.NewEncoder(w).Encode(output) diff --git a/web-frontend/js/run-request.js b/web-frontend/js/run-request.js index e7fc0de..db8094e 100644 --- a/web-frontend/js/run-request.js +++ b/web-frontend/js/run-request.js @@ -67,23 +67,22 @@ async function runCall() { .then(function(result) { let out = JSON.parse(result); - out["error"] = stringify(out["error"]); stdout.innerHTML = - "Stdout: " + out["stdout"].replace(/\n/g, "
"); + "
Stdout: " + out["stdout"] + "
"; stdout.removeAttribute("hidden"); stderr.innerHTML = - "Stderr: " + out["stderr"]; + "
Stderr: " + out["stderr"] + "
"; stderr.removeAttribute("hidden"); - error.innerHTML = "Error: " + out["error"]; + error.innerHTML = "
Error: " + out["error"] + "
"; }) .catch(function(err) { console.log(err); stdout.setAttribute("hidden", true); stderr.setAttribute("hidden", true); - error.innerHTML = "Error: " + stringify(err); + error.innerHTML = "
Error: " + stringify(err) + "
"; }); } diff --git a/web-frontend/style/main.css b/web-frontend/style/main.css index 09ad8d5..1f5b320 100644 --- a/web-frontend/style/main.css +++ b/web-frontend/style/main.css @@ -35,7 +35,7 @@ .field { background-color: #d8d8d8; - color:#282828; + color: #282828; } } @@ -110,7 +110,11 @@ footer { width: 90%; } +pre { + text-wrap: balance; +} + #wrapper { width: 50%; margin-left: 25%; -} \ No newline at end of file +} From 0d15f084dac9e0f72e841583d1dbe606ea60b9aa Mon Sep 17 00:00:00 2001 From: Arek Ouzounian Date: Mon, 24 Jun 2024 15:54:45 -0700 Subject: [PATCH 4/6] update mock --- server/mock-server/main.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/server/mock-server/main.go b/server/mock-server/main.go index 62dd05c..511c864 100644 --- a/server/mock-server/main.go +++ b/server/mock-server/main.go @@ -5,11 +5,12 @@ package main import ( "encoding/json" "fmt" - v2 "github.com/runner-x/runner-x/server/api/v2" "log" "net/http" "time" + v2 "github.com/runner-x/runner-x/server/api/v2" + "github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5/middleware" coderunner "github.com/runner-x/runner-x/engine/coderunner/v2" @@ -41,7 +42,7 @@ func runHandler(w http.ResponseWriter, r *http.Request) { output := v2.RunResponse{ Stdout: "hello world", Stderr: "", - Error: nil, + Error: "", } err := json.NewEncoder(w).Encode(output) From 1947b5589702ac4986964358b330ca89ec6146ca Mon Sep 17 00:00:00 2001 From: Arek Ouzounian Date: Mon, 1 Jul 2024 11:46:18 -0700 Subject: [PATCH 5/6] fix lints --- engine/process/main.go | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/engine/process/main.go b/engine/process/main.go index 5fe328b..af309af 100644 --- a/engine/process/main.go +++ b/engine/process/main.go @@ -33,9 +33,7 @@ const ( DefaultCpuTime = 1 // default max 1s in CPU DefaultStackSize = 262144 // set default stack size to 0.25MB - // TODO: find better way to handle errors EApplyingLimits = 10 // error code for applying limits - ERunningProc = 20 // error code when running command ) // The process CLI is used to handle set limits on the current process/user @@ -102,21 +100,28 @@ func main() { err = cmd.Run() if err != nil { - print.ProcDebug("error running process: %v\n", err) if cast, ok := err.(*exec.ExitError); ok { + print.ProcDebug("exit error encountered: %v\n", err) if ws, ok := cast.Sys().(syscall.WaitStatus); ok { if ws.Signaled() { // more verbose err message - cmd.Stderr.Write([]byte(err.Error())) + _, err := cmd.Stderr.Write([]byte(err.Error())) + if err != nil { + print.ProcDebug("error writing to command stderr: %v", err) + } // signal exit code: 128 + signal code os.Exit(128 + int(ws.Signal())) } + } else { + print.ProcDebug("unable to capture WaitStatus on exit error\n") } // if for some reason we can't get the wait status then we // can just get the (probably incorrect) error code from the cast os.Exit(cast.ExitCode()) + } else { + print.ProcDebug("encountered non exit-error failure: %v\n", err) } } } From 933bd2446a6365e327006033fe1e78d651d5d876 Mon Sep 17 00:00:00 2001 From: camerondurham Date: Mon, 1 Jul 2024 18:30:34 -0700 Subject: [PATCH 6/6] Update controller and server tests --- engine/controller/controller_test.go | 21 ++++++++++++++------- server/main_test.go | 2 +- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/engine/controller/controller_test.go b/engine/controller/controller_test.go index 91de541..78c860a 100644 --- a/engine/controller/controller_test.go +++ b/engine/controller/controller_test.go @@ -98,6 +98,13 @@ func TestSubmitRequest(t *testing.T) { Stderr: "world", } + errorCaseOutput := &runtime.RunOutput{ + Stdout: "", + Stderr: "compilation error", + } + + errorCaseOutputError := errors.New("Error") + preRunProps := &runtime.RunProps{ RunArgs: []string{"echo", "hello", "world"}, Timeout: 0, @@ -296,7 +303,7 @@ func TestSubmitRequest(t *testing.T) { }, }, { - name: "Last runner is ready: pre run cmd error", + name: "Last runner is ready: command error", runProps: &Props{ PreRunProps: preRunProps, RunProps: &runtime.RunProps{}, @@ -313,17 +320,17 @@ func TestSubmitRequest(t *testing.T) { { state: runtime.Ready, shouldBePickedAsRunner: true, - returnOutput: happyCaseOutput, - returnErr: nil, + returnOutput: errorCaseOutput, + returnErr: errorCaseOutputError, writeErr: nil, - preRunErr: errors.New("some error"), + preRunErr: nil, preRunCmd: preRunProps, }, }, want: CtrlRunOutput{ - ControllerErr: PreRunError, - RunOutput: nil, - CommandErr: nil, + ControllerErr: nil, + RunOutput: errorCaseOutput, + CommandErr: errorCaseOutputError, }, }} diff --git a/server/main_test.go b/server/main_test.go index 86e3f2f..e269b20 100644 --- a/server/main_test.go +++ b/server/main_test.go @@ -98,7 +98,7 @@ int main() { args: args{ r: newRequest("POST", "url", api.RunRequest{ Source: "print(\"hello\")", - Lang: coderunner.Go.Name, + Lang: "random-lang", }), expectedStatusCode: 400, },