don't call os.NewFile on unknown FDs

os.NewFile was called on file descriptors 3, 4, and 5 during every init,
in case this process happened to be running inside panicwrap. If the
runtime has already chosen one of these file descriptors to use
internally, starting polling on them can cause the runtime to crash.

Initialize the file descriptors lazily, only if we know that they belong
to us, after Wrapped is checked.
This commit is contained in:
James Bardin 2020-04-04 15:46:19 -04:00
parent 60e407a59b
commit cd65b28da0
2 changed files with 23 additions and 24 deletions

View File

@ -10,34 +10,31 @@ import (
// Stdin returns the true stdin of the process. // Stdin returns the true stdin of the process.
func Stdin() *os.File { func Stdin() *os.File {
stdin := os.Stdin stdin, _, _ := fds()
if panicwrap.Wrapped(nil) {
stdin = wrappedStdin
}
return stdin return stdin
} }
// Stdout returns the true stdout of the process. // Stdout returns the true stdout of the process.
func Stdout() *os.File { func Stdout() *os.File {
stdout := os.Stdout _, stdout, _ := fds()
if panicwrap.Wrapped(nil) {
stdout = wrappedStdout
}
return stdout return stdout
} }
// Stderr returns the true stderr of the process. // Stderr returns the true stderr of the process.
func Stderr() *os.File { func Stderr() *os.File {
stderr := os.Stderr _, _, stderr := fds()
if panicwrap.Wrapped(nil) {
stderr = wrappedStderr
}
return stderr return stderr
} }
func fds() (stdin, stdout, stderr *os.File) {
stdin, stdout, stderr = os.Stdin, os.Stdout, os.Stderr
if panicwrap.Wrapped(nil) {
initPlatform()
stdin, stdout, stderr = wrappedStdin, wrappedStdout, wrappedStderr
}
return
}
// These are the wrapped standard streams. These are setup by the // These are the wrapped standard streams. These are setup by the
// platform specific code in initPlatform. // platform specific code in initPlatform.
var ( var (
@ -45,8 +42,3 @@ var (
wrappedStdout *os.File wrappedStdout *os.File
wrappedStderr *os.File wrappedStderr *os.File
) )
func init() {
// Initialize the platform-specific code
initPlatform()
}

View File

@ -4,11 +4,18 @@ package wrappedstreams
import ( import (
"os" "os"
"sync"
) )
var initOnce sync.Once
func initPlatform() { func initPlatform() {
// These must be initialized lazily, once it's been determined that this is
// a wrapped process.
initOnce.Do(func() {
// The standard streams are passed in via extra file descriptors. // The standard streams are passed in via extra file descriptors.
wrappedStdin = os.NewFile(uintptr(3), "stdin") wrappedStdin = os.NewFile(uintptr(3), "stdin")
wrappedStdout = os.NewFile(uintptr(4), "stdout") wrappedStdout = os.NewFile(uintptr(4), "stdout")
wrappedStderr = os.NewFile(uintptr(5), "stderr") wrappedStderr = os.NewFile(uintptr(5), "stderr")
})
} }