From 17c1e379c2f4cd82aab9549ba5ca5ee9c2fad645 Mon Sep 17 00:00:00 2001 From: Konrad Hanff Date: Thu, 17 Jun 2021 16:41:24 +0200 Subject: [PATCH] Fix busy waiting on stdin When running an execution, Nomad continuously reads from the stdin reader. Because the readers we implemented (codeOceanToRawReader and nullReader) return zero if there is no input available, this leads to busy waiting and a high CPU load on Poseidon. By waiting indefinitely in case of the nullReader and for at least one byte on case of the codeOceanToRawReader before returning, we prevent this issue. --- api/websocket.go | 7 ++++++- nomad/nomad.go | 3 ++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/api/websocket.go b/api/websocket.go index 615ffba..d05a32b 100644 --- a/api/websocket.go +++ b/api/websocket.go @@ -93,7 +93,12 @@ func (cr *codeOceanToRawReader) readInputLoop() context.CancelFunc { // Read implements the io.Reader interface. // It returns bytes from the buffer. func (cr *codeOceanToRawReader) Read(p []byte) (n int, err error) { - for n = 0; n < len(p); n++ { + if len(p) == 0 { + return + } + // Ensure to not return until at least one byte has been read to avoid busy waiting. + p[0] = <-cr.buffer + for n = 1; n < len(p); n++ { select { case p[n] = <-cr.buffer: default: diff --git a/nomad/nomad.go b/nomad/nomad.go index 30057d1..4ce5a64 100644 --- a/nomad/nomad.go +++ b/nomad/nomad.go @@ -292,7 +292,8 @@ func (a *APIClient) LoadEnvironmentJobs() ([]*nomadApi.Job, error) { type nullReader struct{} func (r nullReader) Read(_ []byte) (int, error) { - return 0, nil + // An empty select blocks forever. + select {} } // ExecuteCommand executes the given command in the given allocation.