Use the system.ScanReader function to replace this logic
This commit is contained in:
parent
a4c68eed16
commit
94d41bc1f5
|
@ -2,7 +2,6 @@ package docker
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
|
||||||
"context"
|
"context"
|
||||||
"emperror.dev/errors"
|
"emperror.dev/errors"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
@ -15,6 +14,7 @@ import (
|
||||||
"github.com/docker/docker/daemon/logger/jsonfilelog"
|
"github.com/docker/docker/daemon/logger/jsonfilelog"
|
||||||
"github.com/pterodactyl/wings/config"
|
"github.com/pterodactyl/wings/config"
|
||||||
"github.com/pterodactyl/wings/environment"
|
"github.com/pterodactyl/wings/environment"
|
||||||
|
"github.com/pterodactyl/wings/system"
|
||||||
"io"
|
"io"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -295,60 +295,10 @@ func (e *Environment) followOutput() error {
|
||||||
|
|
||||||
go func(reader io.ReadCloser) {
|
go func(reader io.ReadCloser) {
|
||||||
defer reader.Close()
|
defer reader.Close()
|
||||||
|
evts := e.Events()
|
||||||
r := bufio.NewReader(reader)
|
err := system.ScanReader(reader, func(line string) {
|
||||||
|
evts.Publish(environment.ConsoleOutputEvent, line)
|
||||||
// Micro-optimization to create these replacements one time when this routine
|
})
|
||||||
// fires up, rather than on every line that is executed.
|
|
||||||
cr := []byte(" \r")
|
|
||||||
crr := []byte("\r\n")
|
|
||||||
|
|
||||||
// Avoid constantly re-allocating memory when we're flooding lines through this
|
|
||||||
// function by using the same buffer for the duration of the call and just truncating
|
|
||||||
// the value back to 0 every loop.
|
|
||||||
var str strings.Builder
|
|
||||||
ParentLoop:
|
|
||||||
for {
|
|
||||||
str.Reset()
|
|
||||||
var line []byte
|
|
||||||
var isPrefix bool
|
|
||||||
|
|
||||||
for {
|
|
||||||
// Read the line and write it to the buffer.
|
|
||||||
line, isPrefix, err = r.ReadLine()
|
|
||||||
|
|
||||||
// Certain games like Minecraft output absolutely random carriage returns in the output seemingly
|
|
||||||
// in line with that it thinks is the terminal size. Those returns break a lot of output handling,
|
|
||||||
// so we'll just replace them with proper new-lines and then split it later and send each line as
|
|
||||||
// its own event in the response.
|
|
||||||
str.Write(bytes.Replace(line, cr, crr, -1))
|
|
||||||
|
|
||||||
// Finish this loop and begin outputting the line if there is no prefix (the line fit into
|
|
||||||
// the default buffer), or if we hit the end of the line.
|
|
||||||
if !isPrefix || err == io.EOF {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we encountered an error with something in ReadLine that was not an EOF just abort
|
|
||||||
// the entire process here.
|
|
||||||
if err != nil {
|
|
||||||
break ParentLoop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Publish the line for this loop. Break on new-line characters so every line is sent as a single
|
|
||||||
// output event, otherwise you get funky handling in the browser console.
|
|
||||||
for _, line := range strings.Split(str.String(), "\r\n") {
|
|
||||||
e.Events().Publish(environment.ConsoleOutputEvent, line)
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the error we got previously that lead to the line being output is an io.EOF we want to
|
|
||||||
// exit the entire looping process.
|
|
||||||
if err == io.EOF {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil && err != io.EOF {
|
if err != nil && err != io.EOF {
|
||||||
log.WithField("error", err).WithField("container_id", e.Id).Warn("error processing scanner line in console output")
|
log.WithField("error", err).WithField("container_id", e.Id).Warn("error processing scanner line in console output")
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user