From 01eadf51ea54b8f478c49b755d712f11fff2b28c Mon Sep 17 00:00:00 2001 From: Fabricio Voznika Date: Fri, 6 Dec 2019 23:08:39 -0800 Subject: Bump up Go 1.13 as minimum requirement PiperOrigin-RevId: 284320186 --- pkg/sentry/sighandling/sighandling.go | 75 ++++++++--------------------------- 1 file changed, 16 insertions(+), 59 deletions(-) (limited to 'pkg/sentry/sighandling/sighandling.go') diff --git a/pkg/sentry/sighandling/sighandling.go b/pkg/sentry/sighandling/sighandling.go index 2f65db70b..ba1f9043d 100644 --- a/pkg/sentry/sighandling/sighandling.go +++ b/pkg/sentry/sighandling/sighandling.go @@ -16,7 +16,6 @@ package sighandling import ( - "fmt" "os" "os/signal" "reflect" @@ -31,37 +30,25 @@ const numSignals = 32 // handleSignals listens for incoming signals and calls the given handler // function. // -// It starts when the start channel is closed, stops when the stop channel -// is closed, and closes done once it will no longer deliver signals to k. -func handleSignals(sigchans []chan os.Signal, handler func(linux.Signal), start, stop, done chan struct{}) { +// It stops when the stop channel is closed. The done channel is closed once it +// will no longer deliver signals to k. +func handleSignals(sigchans []chan os.Signal, handler func(linux.Signal), stop, done chan struct{}) { // Build a select case. - sc := []reflect.SelectCase{{Dir: reflect.SelectRecv, Chan: reflect.ValueOf(start)}} + sc := []reflect.SelectCase{{Dir: reflect.SelectRecv, Chan: reflect.ValueOf(stop)}} for _, sigchan := range sigchans { sc = append(sc, reflect.SelectCase{Dir: reflect.SelectRecv, Chan: reflect.ValueOf(sigchan)}) } - started := false for { // Wait for a notification. index, _, ok := reflect.Select(sc) - // Was it the start / stop channel? + // Was it the stop channel? if index == 0 { if !ok { - if !started { - // start channel; start forwarding and - // swap this case for the stop channel - // to select stop requests. - started = true - sc[0] = reflect.SelectCase{Dir: reflect.SelectRecv, Chan: reflect.ValueOf(stop)} - } else { - // stop channel; stop forwarding and - // clear this case so it is never - // selected again. - started = false - close(done) - sc[0].Chan = reflect.Value{} - } + // Stop forwarding and notify that it's done. + close(done) + return } continue } @@ -73,44 +60,17 @@ func handleSignals(sigchans []chan os.Signal, handler func(linux.Signal), start, // Otherwise, it was a signal on channel N. Index 0 represents the stop // channel, so index N represents the channel for signal N. - signal := linux.Signal(index) - - if !started { - // Kernel cannot receive signals, either because it is - // not ready yet or is shutting down. - // - // Kill ourselves if this signal would have killed the - // process before PrepareForwarding was called. i.e., all - // _SigKill signals; see Go - // src/runtime/sigtab_linux_generic.go. - // - // Otherwise ignore the signal. - // - // TODO(b/114489875): Drop in Go 1.12, which uses tgkill - // in runtime.raise. - switch signal { - case linux.SIGHUP, linux.SIGINT, linux.SIGTERM: - dieFromSignal(signal) - panic(fmt.Sprintf("Failed to die from signal %d", signal)) - default: - continue - } - } - - // Pass the signal to the handler. - handler(signal) + handler(linux.Signal(index)) } } -// PrepareHandler ensures that synchronous signals are passed to the given -// handler function and returns a callback that starts signal delivery, which -// itself returns a callback that stops signal handling. +// StartSignalForwarding ensures that synchronous signals are passed to the +// given handler function and returns a callback that stops signal delivery. // // Note that this function permanently takes over signal handling. After the // stop callback, signals revert to the default Go runtime behavior, which // cannot be overridden with external calls to signal.Notify. -func PrepareHandler(handler func(linux.Signal)) func() func() { - start := make(chan struct{}) +func StartSignalForwarding(handler func(linux.Signal)) func() { stop := make(chan struct{}) done := make(chan struct{}) @@ -128,13 +88,10 @@ func PrepareHandler(handler func(linux.Signal)) func() func() { signal.Notify(sigchan, syscall.Signal(sig)) } // Start up our listener. - go handleSignals(sigchans, handler, start, stop, done) // S/R-SAFE: synchronized by Kernel.extMu. + go handleSignals(sigchans, handler, stop, done) // S/R-SAFE: synchronized by Kernel.extMu. - return func() func() { - close(start) - return func() { - close(stop) - <-done - } + return func() { + close(stop) + <-done } } -- cgit v1.2.3 From 2aa9514a06a5e34894e606d508ac2df53b082c74 Mon Sep 17 00:00:00 2001 From: Andrei Vagin Date: Wed, 11 Mar 2020 09:49:06 -0700 Subject: runsc: don't redirect SIGURG which is used by Go's runtime scheduler Go 1.14+ sends SIGURG to Ms to attempt asynchronous preemption of a G. Since it can't guarantee that a SIGURG is only related to preemption, it continues to forward them to signal.Notify (see runtime.sighandler). When runsc is running a container, there are three processes: a parent process and two children (sandbox and gopher). A parent process sets a signal handler for all signals and redirect them to the container init process. This logic should ignore SIGURG signals. We already ignore them in the Sentry, but it will be better to not notify about them when this is possible. PiperOrigin-RevId: 300345286 --- pkg/sentry/sighandling/sighandling.go | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'pkg/sentry/sighandling/sighandling.go') diff --git a/pkg/sentry/sighandling/sighandling.go b/pkg/sentry/sighandling/sighandling.go index ba1f9043d..959ef7217 100644 --- a/pkg/sentry/sighandling/sighandling.go +++ b/pkg/sentry/sighandling/sighandling.go @@ -83,6 +83,10 @@ func StartSignalForwarding(handler func(linux.Signal)) func() { // for their handling. var sigchans []chan os.Signal for sig := 1; sig <= numSignals+1; sig++ { + // SIGURG is used by Go's runtime scheduler. + if sig == int(linux.SIGURG) { + continue + } sigchan := make(chan os.Signal, 1) sigchans = append(sigchans, sigchan) signal.Notify(sigchan, syscall.Signal(sig)) -- cgit v1.2.3 From f458a325e9b6aecf2ee198de19063505c48a14d7 Mon Sep 17 00:00:00 2001 From: Ting-Yu Wang Date: Fri, 13 Mar 2020 11:25:49 -0700 Subject: Fix "application exiting with {Code:0 Signo:27}" during boot. 2aa9514a06a5e34894e606d508ac2df53b082c74 skips SIGURG, but later code expects the sigchans array contains consecutive signal numbers. PiperOrigin-RevId: 300793450 --- pkg/sentry/sighandling/sighandling.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'pkg/sentry/sighandling/sighandling.go') diff --git a/pkg/sentry/sighandling/sighandling.go b/pkg/sentry/sighandling/sighandling.go index 959ef7217..83195d5a1 100644 --- a/pkg/sentry/sighandling/sighandling.go +++ b/pkg/sentry/sighandling/sighandling.go @@ -83,12 +83,13 @@ func StartSignalForwarding(handler func(linux.Signal)) func() { // for their handling. var sigchans []chan os.Signal for sig := 1; sig <= numSignals+1; sig++ { + sigchan := make(chan os.Signal, 1) + sigchans = append(sigchans, sigchan) + // SIGURG is used by Go's runtime scheduler. if sig == int(linux.SIGURG) { continue } - sigchan := make(chan os.Signal, 1) - sigchans = append(sigchans, sigchan) signal.Notify(sigchan, syscall.Signal(sig)) } // Start up our listener. -- cgit v1.2.3