summaryrefslogtreecommitdiffhomepage
path: root/pkg/sighandling
diff options
context:
space:
mode:
authorEtienne Perot <eperot@google.com>2021-09-28 16:53:22 -0700
committergVisor bot <gvisor-bot@google.com>2021-09-28 16:56:39 -0700
commit65698b627e81d0b078a5f993260f6359e22e7970 (patch)
tree51e7538c52a8c60666056e8fac8b777055336892 /pkg/sighandling
parentfa4c30c635b8d46f8a284f6e6cdd6f6385686daa (diff)
Move `safecopy.ReplaceSignalHandler` into `sighandling` package.
PiperOrigin-RevId: 399560357
Diffstat (limited to 'pkg/sighandling')
-rw-r--r--pkg/sighandling/sighandling_unsafe.go34
1 files changed, 34 insertions, 0 deletions
diff --git a/pkg/sighandling/sighandling_unsafe.go b/pkg/sighandling/sighandling_unsafe.go
index 3fe5c6770..7deeda042 100644
--- a/pkg/sighandling/sighandling_unsafe.go
+++ b/pkg/sighandling/sighandling_unsafe.go
@@ -15,6 +15,7 @@
package sighandling
import (
+ "fmt"
"unsafe"
"golang.org/x/sys/unix"
@@ -37,3 +38,36 @@ func IgnoreChildStop() error {
return nil
}
+
+// ReplaceSignalHandler replaces the existing signal handler for the provided
+// signal with the function pointer at `handler`. This bypasses the Go runtime
+// signal handlers, and should only be used for low-level signal handlers where
+// use of signal.Notify is not appropriate.
+//
+// It stores the value of the previously set handler in previous.
+func ReplaceSignalHandler(sig unix.Signal, handler uintptr, previous *uintptr) error {
+ var sa linux.SigAction
+ const maskLen = 8
+
+ // Get the existing signal handler information, and save the current
+ // handler. Once we replace it, we will use this pointer to fall back to
+ // it when we receive other signals.
+ if _, _, e := unix.RawSyscall6(unix.SYS_RT_SIGACTION, uintptr(sig), 0, uintptr(unsafe.Pointer(&sa)), maskLen, 0, 0); e != 0 {
+ return e
+ }
+
+ // Fail if there isn't a previous handler.
+ if sa.Handler == 0 {
+ return fmt.Errorf("previous handler for signal %x isn't set", sig)
+ }
+
+ *previous = uintptr(sa.Handler)
+
+ // Install our own handler.
+ sa.Handler = uint64(handler)
+ if _, _, e := unix.RawSyscall6(unix.SYS_RT_SIGACTION, uintptr(sig), uintptr(unsafe.Pointer(&sa)), 0, maskLen, 0, 0); e != 0 {
+ return e
+ }
+
+ return nil
+}