container/init: improve signal handling
	
		
			
	
		
	
	
		
	
		
			All checks were successful
		
		
	
	
		
			
				
	
				Test / Create distribution (push) Successful in 32s
				
			
		
			
				
	
				Test / Sandbox (push) Successful in 2m9s
				
			
		
			
				
	
				Test / Hakurei (push) Successful in 3m9s
				
			
		
			
				
	
				Test / Sandbox (race detector) (push) Successful in 3m57s
				
			
		
			
				
	
				Test / Hpkg (push) Successful in 3m58s
				
			
		
			
				
	
				Test / Hakurei (race detector) (push) Successful in 4m43s
				
			
		
			
				
	
				Test / Flake checks (push) Successful in 1m30s
				
			
		
		
	
	
				
					
				
			
		
			All checks were successful
		
		
	
	Test / Create distribution (push) Successful in 32s
				
			Test / Sandbox (push) Successful in 2m9s
				
			Test / Hakurei (push) Successful in 3m9s
				
			Test / Sandbox (race detector) (push) Successful in 3m57s
				
			Test / Hpkg (push) Successful in 3m58s
				
			Test / Hakurei (race detector) (push) Successful in 4m43s
				
			Test / Flake checks (push) Successful in 1m30s
				
			The SIGTERM signal is delivered in many other cases and can lead to strange behaviour. The unconditional resume of the logger also causes strange behaviour in the cancellation forwarding path. This change also passes through additional signals. Signed-off-by: Ophestra <cat@gensokyo.uk>
This commit is contained in:
		
							parent
							
								
									c5aefe5e9d
								
							
						
					
					
						commit
						57231d4acf
					
				| @ -24,7 +24,7 @@ import ( | ||||
| const ( | ||||
| 	// CancelSignal is the signal expected by container init on context cancel. | ||||
| 	// A custom [Container.Cancel] function must eventually deliver this signal. | ||||
| 	CancelSignal = SIGTERM | ||||
| 	CancelSignal = SIGUSR2 | ||||
| ) | ||||
| 
 | ||||
| type ( | ||||
|  | ||||
| @ -390,7 +390,8 @@ func initEntrypoint(k syscallDispatcher, msg message.Msg) { | ||||
| 
 | ||||
| 	// handle signals to dump withheld messages | ||||
| 	sig := make(chan os.Signal, 2) | ||||
| 	k.notify(sig, os.Interrupt, CancelSignal) | ||||
| 	k.notify(sig, CancelSignal, | ||||
| 		os.Interrupt, SIGTERM, SIGQUIT) | ||||
| 
 | ||||
| 	// closed after residualProcessTimeout has elapsed after initial process death | ||||
| 	timeout := make(chan struct{}) | ||||
| @ -399,18 +400,28 @@ func initEntrypoint(k syscallDispatcher, msg message.Msg) { | ||||
| 	for { | ||||
| 		select { | ||||
| 		case s := <-sig: | ||||
| 			if msg.Resume() { | ||||
| 				msg.Verbosef("%s after process start", s.String()) | ||||
| 			} else { | ||||
| 				msg.Verbosef("got %s", s.String()) | ||||
| 			} | ||||
| 			if s == CancelSignal && params.ForwardCancel && cmd.Process != nil { | ||||
| 				msg.Resume() | ||||
| 				msg.Verbose("forwarding context cancellation") | ||||
| 				if err := k.signal(cmd, os.Interrupt); err != nil { | ||||
| 					k.printf(msg, "cannot forward cancellation: %v", err) | ||||
| 				} | ||||
| 				continue | ||||
| 			} | ||||
| 
 | ||||
| 			if s == SIGTERM || s == SIGQUIT { | ||||
| 				msg.Verbosef("got %s, forwarding to initial process", s.String()) | ||||
| 				if err := k.signal(cmd, s); err != nil { | ||||
| 					k.printf(msg, "cannot forward signal: %v", err) | ||||
| 				} | ||||
| 				continue | ||||
| 			} | ||||
| 
 | ||||
| 			if msg.Resume() { | ||||
| 				msg.Verbosef("%s after process start", s.String()) | ||||
| 			} else { | ||||
| 				msg.Verbosef("got %s", s.String()) | ||||
| 			} | ||||
| 			msg.BeforeExit() | ||||
| 			k.exit(0) | ||||
| 
 | ||||
|  | ||||
| @ -2065,9 +2065,8 @@ func TestInitEntrypoint(t *testing.T) { | ||||
| 				call("suspend", stub.ExpectArgs{}, true, nil), | ||||
| 				call("printf", stub.ExpectArgs{"cannot close setup pipe: %v", []any{stub.UniqueError(10)}}, nil, nil), | ||||
| 				call("New", stub.ExpectArgs{}, nil, nil), | ||||
| 				call("notify", stub.ExpectArgs{func(c chan<- os.Signal) { c <- CancelSignal }, []os.Signal{syscall.SIGINT, syscall.SIGTERM}}, nil, nil), | ||||
| 				call("notify", stub.ExpectArgs{func(c chan<- os.Signal) { c <- CancelSignal }, []os.Signal{CancelSignal, os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT}}, nil, nil), | ||||
| 				call("resume", stub.ExpectArgs{}, true, nil), | ||||
| 				call("verbosef", stub.ExpectArgs{"%s after process start", []any{"terminated"}}, nil, nil), | ||||
| 				call("verbose", stub.ExpectArgs{[]any{"forwarding context cancellation"}}, nil, nil), | ||||
| 				// magicWait4Signal as ret causes wait4 stub to unblock | ||||
| 				call("signal", stub.ExpectArgs{"/run/current-system/sw/bin/bash", []string{"bash", "-c", "false"}, ([]string)(nil), "/.hakurei/nonexistent", os.Interrupt}, magicWait4Signal, stub.UniqueError(9)), | ||||
| @ -2090,6 +2089,199 @@ func TestInitEntrypoint(t *testing.T) { | ||||
| 			}}}, | ||||
| 		}, nil}, | ||||
| 
 | ||||
| 		{"lowlastcap signaled cancel passthrough", func(k *kstub) error { initEntrypoint(k, k); return nil }, stub.Expect{ | ||||
| 			/* entrypoint */ | ||||
| 			Calls: []stub.Call{ | ||||
| 				call("lockOSThread", stub.ExpectArgs{}, nil, nil), | ||||
| 				call("getpid", stub.ExpectArgs{}, 1, nil), | ||||
| 				call("setPtracer", stub.ExpectArgs{uintptr(0)}, 0, stub.UniqueError(8)), | ||||
| 				call("verbosef", stub.ExpectArgs{"cannot enable ptrace protection via Yama LSM: %v", []any{stub.UniqueError(8)}}, nil, nil), | ||||
| 				call("receive", stub.ExpectArgs{"HAKUREI_SETUP", new(initParams), new(uintptr), &initParams{Params{ | ||||
| 					Dir:            check.MustAbs("/.hakurei/nonexistent"), | ||||
| 					Path:           check.MustAbs("/run/current-system/sw/bin/bash"), | ||||
| 					Args:           []string{"bash", "-c", "false"}, | ||||
| 					ForwardCancel:  true, | ||||
| 					AdoptWaitDelay: 5 * time.Nanosecond, | ||||
| 					Uid:            1 << 24, | ||||
| 					Gid:            1 << 47, | ||||
| 					Hostname:       "hakurei-check", | ||||
| 					Ops:            new(Ops).Bind(check.MustAbs("/"), check.MustAbs("/"), comp.BindDevice).Proc(check.MustAbs("/proc/")), | ||||
| 					SeccompRules:   make([]seccomp.NativeRule, 0), | ||||
| 					SeccompDisable: true, | ||||
| 					ParentPerm:     0750, | ||||
| 				}, 1971, 127, 2, false}, uintptr(0x39)}, stub.UniqueError(7), nil), | ||||
| 				call("swapVerbose", stub.ExpectArgs{false}, false, nil), | ||||
| 				call("verbose", stub.ExpectArgs{[]any{"received setup parameters"}}, nil, nil), | ||||
| 				call("setDumpable", stub.ExpectArgs{uintptr(1)}, nil, nil), | ||||
| 				call("writeFile", stub.ExpectArgs{"/proc/self/uid_map", []byte("16777216 1971 1\n"), os.FileMode(0)}, nil, nil), | ||||
| 				call("writeFile", stub.ExpectArgs{"/proc/self/setgroups", []byte("deny\n"), os.FileMode(0)}, nil, nil), | ||||
| 				call("writeFile", stub.ExpectArgs{"/proc/self/gid_map", []byte("140737488355328 127 1\n"), os.FileMode(0)}, nil, nil), | ||||
| 				call("setDumpable", stub.ExpectArgs{uintptr(0)}, nil, nil), | ||||
| 				call("umask", stub.ExpectArgs{0}, 022, nil), | ||||
| 				call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil), | ||||
| 				call("lastcap", stub.ExpectArgs{}, uintptr(4), nil), | ||||
| 				call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil), | ||||
| 				/* begin early */ | ||||
| 				call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil), | ||||
| 				/* end early */ | ||||
| 				call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil), | ||||
| 				call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil), | ||||
| 				call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil), | ||||
| 				call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil), | ||||
| 				call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil), | ||||
| 				call("pivotRoot", stub.ExpectArgs{"/proc/self/fd", "host"}, nil, nil), | ||||
| 				call("chdir", stub.ExpectArgs{"/"}, nil, nil), | ||||
| 				/* begin apply */ | ||||
| 				call("stat", stub.ExpectArgs{"/host"}, isDirFi(true), nil), | ||||
| 				call("mkdirAll", stub.ExpectArgs{"/sysroot", os.FileMode(0700)}, nil, nil), | ||||
| 				call("verbosef", stub.ExpectArgs{"mounting %q flags %#x", []any{"/sysroot", uintptr(0x4001)}}, nil, nil), | ||||
| 				call("bindMount", stub.ExpectArgs{"/host", "/sysroot", uintptr(0x4001), false}, nil, nil), | ||||
| 				call("verbosef", stub.ExpectArgs{"%s %s", []any{"mounting", &MountProcOp{Target: check.MustAbs("/proc/")}}}, nil, nil), | ||||
| 				call("mkdirAll", stub.ExpectArgs{"/sysroot/proc", os.FileMode(0750)}, nil, nil), | ||||
| 				call("mount", stub.ExpectArgs{"proc", "/sysroot/proc", "proc", uintptr(0xe), ""}, nil, nil), | ||||
| 				/* end apply */ | ||||
| 				call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil), | ||||
| 				call("unmount", stub.ExpectArgs{"host", 2}, nil, nil), | ||||
| 				call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, syscall.EINTR), | ||||
| 				call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, nil), | ||||
| 				call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil), | ||||
| 				call("pivotRoot", stub.ExpectArgs{".", "."}, nil, nil), | ||||
| 				call("fchdir", stub.ExpectArgs{1 << 35}, nil, nil), | ||||
| 				call("unmount", stub.ExpectArgs{".", 2}, nil, nil), | ||||
| 				call("chdir", stub.ExpectArgs{"/"}, nil, nil), | ||||
| 				call("close", stub.ExpectArgs{1 << 35}, nil, nil), | ||||
| 				call("capAmbientClearAll", stub.ExpectArgs{}, nil, nil), | ||||
| 				call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x0)}, nil, nil), | ||||
| 				call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x1)}, nil, nil), | ||||
| 				call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x2)}, nil, nil), | ||||
| 				call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x3)}, nil, nil), | ||||
| 				call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x4)}, nil, nil), | ||||
| 				call("capset", stub.ExpectArgs{&capHeader{_LINUX_CAPABILITY_VERSION_3, 0}, new([2]capData)}, nil, nil), | ||||
| 				call("verbose", stub.ExpectArgs{[]any{"syscall filter not configured"}}, nil, nil), | ||||
| 				call("newFile", stub.ExpectArgs{uintptr(0x3a), "extra file 0"}, (*os.File)(nil), nil), | ||||
| 				call("newFile", stub.ExpectArgs{uintptr(0x3b), "extra file 1"}, (*os.File)(nil), nil), | ||||
| 				call("umask", stub.ExpectArgs{022}, 0, nil), | ||||
| 				call("verbosef", stub.ExpectArgs{"starting initial program %s", []any{check.MustAbs("/run/current-system/sw/bin/bash")}}, nil, nil), | ||||
| 				call("start", stub.ExpectArgs{"/run/current-system/sw/bin/bash", []string{"bash", "-c", "false"}, ([]string)(nil), "/.hakurei/nonexistent"}, &os.Process{Pid: 0xbad}, nil), | ||||
| 				call("suspend", stub.ExpectArgs{}, true, nil), | ||||
| 				call("printf", stub.ExpectArgs{"cannot close setup pipe: %v", []any{stub.UniqueError(7)}}, nil, nil), | ||||
| 				call("New", stub.ExpectArgs{}, nil, nil), | ||||
| 				call("notify", stub.ExpectArgs{func(c chan<- os.Signal) { c <- syscall.SIGQUIT }, []os.Signal{CancelSignal, os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT}}, nil, nil), | ||||
| 				call("verbosef", stub.ExpectArgs{"got %s, forwarding to initial process", []any{"quit"}}, nil, nil), | ||||
| 				// magicWait4Signal as ret causes wait4 stub to unblock | ||||
| 				call("signal", stub.ExpectArgs{"/run/current-system/sw/bin/bash", []string{"bash", "-c", "false"}, ([]string)(nil), "/.hakurei/nonexistent", syscall.SIGQUIT}, magicWait4Signal, stub.UniqueError(0xfe)), | ||||
| 				call("printf", stub.ExpectArgs{"cannot forward signal: %v", []any{stub.UniqueError(0xfe)}}, nil, nil), | ||||
| 				call("resume", stub.ExpectArgs{}, true, nil), | ||||
| 				call("verbosef", stub.ExpectArgs{"initial process exited with signal %s", []any{syscall.Signal(0x4e)}}, nil, nil), | ||||
| 				call("printf", stub.ExpectArgs{"timeout exceeded waiting for lingering processes", []any(nil)}, nil, nil), | ||||
| 				call("beforeExit", stub.ExpectArgs{}, nil, nil), | ||||
| 				call("exit", stub.ExpectArgs{206}, nil, nil), | ||||
| 			}, | ||||
| 
 | ||||
| 			/* wait4 */ | ||||
| 			Tracks: []stub.Expect{{Calls: []stub.Call{ | ||||
| 				call("lockOSThread", stub.ExpectArgs{}, nil, nil), | ||||
| 
 | ||||
| 				// magicWait4Signal as args[4] causes this to block until simulated signal is delivered | ||||
| 				call("wait4", stub.ExpectArgs{-1, syscall.WaitStatus(0xfade01ce), 0, nil, magicWait4Signal}, 0xbad, nil), | ||||
| 				// this terminates the goroutine at the call, preventing it from leaking while preserving behaviour | ||||
| 				call("wait4", stub.ExpectArgs{-1, nil, 0, nil, stub.PanicExit}, 0, syscall.ECHILD), | ||||
| 			}}}, | ||||
| 		}, nil}, | ||||
| 
 | ||||
| 		{"lowlastcap signaled cancel resumed", func(k *kstub) error { initEntrypoint(k, k); return nil }, stub.Expect{ | ||||
| 			/* entrypoint */ | ||||
| 			Calls: []stub.Call{ | ||||
| 				call("lockOSThread", stub.ExpectArgs{}, nil, nil), | ||||
| 				call("getpid", stub.ExpectArgs{}, 1, nil), | ||||
| 				call("setPtracer", stub.ExpectArgs{uintptr(0)}, 0, stub.UniqueError(8)), | ||||
| 				call("verbosef", stub.ExpectArgs{"cannot enable ptrace protection via Yama LSM: %v", []any{stub.UniqueError(8)}}, nil, nil), | ||||
| 				call("receive", stub.ExpectArgs{"HAKUREI_SETUP", new(initParams), new(uintptr), &initParams{Params{ | ||||
| 					Dir:            check.MustAbs("/.hakurei/nonexistent"), | ||||
| 					Path:           check.MustAbs("/run/current-system/sw/bin/bash"), | ||||
| 					Args:           []string{"bash", "-c", "false"}, | ||||
| 					ForwardCancel:  true, | ||||
| 					AdoptWaitDelay: 5 * time.Nanosecond, | ||||
| 					Uid:            1 << 24, | ||||
| 					Gid:            1 << 47, | ||||
| 					Hostname:       "hakurei-check", | ||||
| 					Ops:            new(Ops).Bind(check.MustAbs("/"), check.MustAbs("/"), comp.BindDevice).Proc(check.MustAbs("/proc/")), | ||||
| 					SeccompRules:   make([]seccomp.NativeRule, 0), | ||||
| 					SeccompDisable: true, | ||||
| 					ParentPerm:     0750, | ||||
| 				}, 1971, 127, 2, false}, uintptr(0x39)}, stub.UniqueError(7), nil), | ||||
| 				call("swapVerbose", stub.ExpectArgs{false}, false, nil), | ||||
| 				call("verbose", stub.ExpectArgs{[]any{"received setup parameters"}}, nil, nil), | ||||
| 				call("setDumpable", stub.ExpectArgs{uintptr(1)}, nil, nil), | ||||
| 				call("writeFile", stub.ExpectArgs{"/proc/self/uid_map", []byte("16777216 1971 1\n"), os.FileMode(0)}, nil, nil), | ||||
| 				call("writeFile", stub.ExpectArgs{"/proc/self/setgroups", []byte("deny\n"), os.FileMode(0)}, nil, nil), | ||||
| 				call("writeFile", stub.ExpectArgs{"/proc/self/gid_map", []byte("140737488355328 127 1\n"), os.FileMode(0)}, nil, nil), | ||||
| 				call("setDumpable", stub.ExpectArgs{uintptr(0)}, nil, nil), | ||||
| 				call("umask", stub.ExpectArgs{0}, 022, nil), | ||||
| 				call("sethostname", stub.ExpectArgs{[]byte("hakurei-check")}, nil, nil), | ||||
| 				call("lastcap", stub.ExpectArgs{}, uintptr(4), nil), | ||||
| 				call("mount", stub.ExpectArgs{"", "/", "", uintptr(0x8c000), ""}, nil, nil), | ||||
| 				/* begin early */ | ||||
| 				call("evalSymlinks", stub.ExpectArgs{"/"}, "/", nil), | ||||
| 				/* end early */ | ||||
| 				call("mount", stub.ExpectArgs{"rootfs", "/proc/self/fd", "tmpfs", uintptr(6), ""}, nil, nil), | ||||
| 				call("chdir", stub.ExpectArgs{"/proc/self/fd"}, nil, nil), | ||||
| 				call("mkdir", stub.ExpectArgs{"sysroot", os.FileMode(0755)}, nil, nil), | ||||
| 				call("mount", stub.ExpectArgs{"sysroot", "sysroot", "", uintptr(0xd000), ""}, nil, nil), | ||||
| 				call("mkdir", stub.ExpectArgs{"host", os.FileMode(0755)}, nil, nil), | ||||
| 				call("pivotRoot", stub.ExpectArgs{"/proc/self/fd", "host"}, nil, nil), | ||||
| 				call("chdir", stub.ExpectArgs{"/"}, nil, nil), | ||||
| 				/* begin apply */ | ||||
| 				call("stat", stub.ExpectArgs{"/host"}, isDirFi(true), nil), | ||||
| 				call("mkdirAll", stub.ExpectArgs{"/sysroot", os.FileMode(0700)}, nil, nil), | ||||
| 				call("verbosef", stub.ExpectArgs{"mounting %q flags %#x", []any{"/sysroot", uintptr(0x4001)}}, nil, nil), | ||||
| 				call("bindMount", stub.ExpectArgs{"/host", "/sysroot", uintptr(0x4001), false}, nil, nil), | ||||
| 				call("verbosef", stub.ExpectArgs{"%s %s", []any{"mounting", &MountProcOp{Target: check.MustAbs("/proc/")}}}, nil, nil), | ||||
| 				call("mkdirAll", stub.ExpectArgs{"/sysroot/proc", os.FileMode(0750)}, nil, nil), | ||||
| 				call("mount", stub.ExpectArgs{"proc", "/sysroot/proc", "proc", uintptr(0xe), ""}, nil, nil), | ||||
| 				/* end apply */ | ||||
| 				call("mount", stub.ExpectArgs{"host", "host", "", uintptr(0x4c000), ""}, nil, nil), | ||||
| 				call("unmount", stub.ExpectArgs{"host", 2}, nil, nil), | ||||
| 				call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, syscall.EINTR), | ||||
| 				call("open", stub.ExpectArgs{"/", syscall.O_DIRECTORY | syscall.O_RDONLY, uint32(0)}, 1<<35, nil), | ||||
| 				call("chdir", stub.ExpectArgs{"/sysroot"}, nil, nil), | ||||
| 				call("pivotRoot", stub.ExpectArgs{".", "."}, nil, nil), | ||||
| 				call("fchdir", stub.ExpectArgs{1 << 35}, nil, nil), | ||||
| 				call("unmount", stub.ExpectArgs{".", 2}, nil, nil), | ||||
| 				call("chdir", stub.ExpectArgs{"/"}, nil, nil), | ||||
| 				call("close", stub.ExpectArgs{1 << 35}, nil, nil), | ||||
| 				call("capAmbientClearAll", stub.ExpectArgs{}, nil, nil), | ||||
| 				call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x0)}, nil, nil), | ||||
| 				call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x1)}, nil, nil), | ||||
| 				call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x2)}, nil, nil), | ||||
| 				call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x3)}, nil, nil), | ||||
| 				call("capBoundingSetDrop", stub.ExpectArgs{uintptr(0x4)}, nil, nil), | ||||
| 				call("capset", stub.ExpectArgs{&capHeader{_LINUX_CAPABILITY_VERSION_3, 0}, new([2]capData)}, nil, nil), | ||||
| 				call("verbose", stub.ExpectArgs{[]any{"syscall filter not configured"}}, nil, nil), | ||||
| 				call("newFile", stub.ExpectArgs{uintptr(0x3a), "extra file 0"}, (*os.File)(nil), nil), | ||||
| 				call("newFile", stub.ExpectArgs{uintptr(0x3b), "extra file 1"}, (*os.File)(nil), nil), | ||||
| 				call("umask", stub.ExpectArgs{022}, 0, nil), | ||||
| 				call("verbosef", stub.ExpectArgs{"starting initial program %s", []any{check.MustAbs("/run/current-system/sw/bin/bash")}}, nil, nil), | ||||
| 				call("start", stub.ExpectArgs{"/run/current-system/sw/bin/bash", []string{"bash", "-c", "false"}, ([]string)(nil), "/.hakurei/nonexistent"}, &os.Process{Pid: 0xbad}, nil), | ||||
| 				call("suspend", stub.ExpectArgs{}, true, nil), | ||||
| 				call("printf", stub.ExpectArgs{"cannot close setup pipe: %v", []any{stub.UniqueError(7)}}, nil, nil), | ||||
| 				call("New", stub.ExpectArgs{}, nil, nil), | ||||
| 				call("notify", stub.ExpectArgs{func(c chan<- os.Signal) { c <- os.Interrupt }, []os.Signal{CancelSignal, os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT}}, nil, nil), | ||||
| 				call("resume", stub.ExpectArgs{}, true, nil), | ||||
| 				call("verbosef", stub.ExpectArgs{"%s after process start", []any{"interrupt"}}, nil, nil), | ||||
| 				call("beforeExit", stub.ExpectArgs{}, nil, nil), | ||||
| 				call("exit", stub.ExpectArgs{0}, nil, nil), | ||||
| 			}, | ||||
| 
 | ||||
| 			/* wait4 */ | ||||
| 			Tracks: []stub.Expect{{Calls: []stub.Call{ | ||||
| 				call("lockOSThread", stub.ExpectArgs{}, nil, nil), | ||||
| 
 | ||||
| 				// this terminates the goroutine at the call, preventing it from leaking while preserving behaviour | ||||
| 				call("wait4", stub.ExpectArgs{-1, nil, 0, nil, stub.PanicExit}, 0, syscall.ECHILD), | ||||
| 			}}}, | ||||
| 		}, nil}, | ||||
| 
 | ||||
| 		{"lowlastcap signaled cancel", func(k *kstub) error { initEntrypoint(k, k); return nil }, stub.Expect{ | ||||
| 			/* entrypoint */ | ||||
| 			Calls: []stub.Call{ | ||||
| @ -2167,7 +2359,7 @@ func TestInitEntrypoint(t *testing.T) { | ||||
| 				call("suspend", stub.ExpectArgs{}, true, nil), | ||||
| 				call("printf", stub.ExpectArgs{"cannot close setup pipe: %v", []any{stub.UniqueError(7)}}, nil, nil), | ||||
| 				call("New", stub.ExpectArgs{}, nil, nil), | ||||
| 				call("notify", stub.ExpectArgs{func(c chan<- os.Signal) { c <- os.Interrupt }, []os.Signal{syscall.SIGINT, syscall.SIGTERM}}, nil, nil), | ||||
| 				call("notify", stub.ExpectArgs{func(c chan<- os.Signal) { c <- os.Interrupt }, []os.Signal{CancelSignal, os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT}}, nil, nil), | ||||
| 				call("resume", stub.ExpectArgs{}, false, nil), | ||||
| 				call("verbosef", stub.ExpectArgs{"got %s", []any{"interrupt"}}, nil, nil), | ||||
| 				call("beforeExit", stub.ExpectArgs{}, nil, nil), | ||||
| @ -2260,7 +2452,7 @@ func TestInitEntrypoint(t *testing.T) { | ||||
| 				call("suspend", stub.ExpectArgs{}, true, nil), | ||||
| 				call("printf", stub.ExpectArgs{"cannot close setup pipe: %v", []any{stub.UniqueError(5)}}, nil, nil), | ||||
| 				call("New", stub.ExpectArgs{}, nil, nil), | ||||
| 				call("notify", stub.ExpectArgs{nil, []os.Signal{syscall.SIGINT, syscall.SIGTERM}}, nil, nil), | ||||
| 				call("notify", stub.ExpectArgs{nil, []os.Signal{CancelSignal, os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT}}, nil, nil), | ||||
| 				call("resume", stub.ExpectArgs{}, true, nil), | ||||
| 				call("verbosef", stub.ExpectArgs{"initial process exited with signal %s", []any{syscall.Signal(0x4e)}}, nil, nil), | ||||
| 				call("printf", stub.ExpectArgs{"timeout exceeded waiting for lingering processes", ([]any)(nil)}, nil, nil), | ||||
| @ -2355,7 +2547,7 @@ func TestInitEntrypoint(t *testing.T) { | ||||
| 				call("suspend", stub.ExpectArgs{}, true, nil), | ||||
| 				call("printf", stub.ExpectArgs{"cannot close setup pipe: %v", []any{stub.UniqueError(3)}}, nil, nil), | ||||
| 				call("New", stub.ExpectArgs{}, nil, nil), | ||||
| 				call("notify", stub.ExpectArgs{nil, []os.Signal{syscall.SIGINT, syscall.SIGTERM}}, nil, nil), | ||||
| 				call("notify", stub.ExpectArgs{nil, []os.Signal{CancelSignal, os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT}}, nil, nil), | ||||
| 				call("resume", stub.ExpectArgs{}, true, nil), | ||||
| 				call("verbosef", stub.ExpectArgs{"initial process exited with signal %s", []any{syscall.Signal(0x4e)}}, nil, nil), | ||||
| 				call("beforeExit", stub.ExpectArgs{}, nil, nil), | ||||
| @ -2493,7 +2685,7 @@ func TestInitEntrypoint(t *testing.T) { | ||||
| 				call("suspend", stub.ExpectArgs{}, true, nil), | ||||
| 				call("printf", stub.ExpectArgs{"cannot close setup pipe: %v", []any{stub.UniqueError(1)}}, nil, nil), | ||||
| 				call("New", stub.ExpectArgs{}, nil, nil), | ||||
| 				call("notify", stub.ExpectArgs{nil, []os.Signal{syscall.SIGINT, syscall.SIGTERM}}, nil, nil), | ||||
| 				call("notify", stub.ExpectArgs{nil, []os.Signal{CancelSignal, os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT}}, nil, nil), | ||||
| 				call("resume", stub.ExpectArgs{}, true, nil), | ||||
| 				call("verbosef", stub.ExpectArgs{"initial process exited with code %d", []any{1}}, nil, nil), | ||||
| 				call("beforeExit", stub.ExpectArgs{}, nil, nil), | ||||
| @ -2635,7 +2827,7 @@ func TestInitEntrypoint(t *testing.T) { | ||||
| 				call("suspend", stub.ExpectArgs{}, true, nil), | ||||
| 				call("printf", stub.ExpectArgs{"cannot close setup pipe: %v", []any{stub.UniqueError(0)}}, nil, nil), | ||||
| 				call("New", stub.ExpectArgs{}, nil, nil), | ||||
| 				call("notify", stub.ExpectArgs{nil, []os.Signal{syscall.SIGINT, syscall.SIGTERM}}, nil, nil), | ||||
| 				call("notify", stub.ExpectArgs{nil, []os.Signal{CancelSignal, os.Interrupt, syscall.SIGTERM, syscall.SIGQUIT}}, nil, nil), | ||||
| 				call("resume", stub.ExpectArgs{}, true, nil), | ||||
| 				call("verbosef", stub.ExpectArgs{"initial process exited with status %#x", []any{syscall.WaitStatus(0xfade007f)}}, nil, nil), | ||||
| 				call("beforeExit", stub.ExpectArgs{}, nil, nil), | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user