-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Sentry systrap: exit the entire process when one stubprocess is dead #11590
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Sentry systrap: exit the entire process when one stubprocess is dead #11590
Conversation
|
@avagin could you take a look? Thanks The changes in the commit 16dba7f#diff-06bbaf439d32bed64b39754ca405a6b8fe4227925bfa92c11428b6ddfc91b962 do not correspond to the comments gvisor/pkg/sentry/platform/systrap/subprocess_linux.go Lines 36 to 43 in 16dba7f
|
We do not squash commits, therefore all commits will be present in the upstream repository after merging. Please take this into account and write proper commit messages. |
What process did you kill? Do you kill a stub process? In the strace log, we see that a guest process associated with the killed stub process exited. The sandbox didn't exit, because there was the init process. Did it wait for the killed process? Why didn't it exit? Could you attach the full sentry log?
If we fork a stub process with SIGKILL, the entire sentry will be killed if a stub process crashes. The commit message says that we handle stub process crashes instead of just killing the sentry. |
|
sentry.log
The process is a subprocess of |
|
@avagin regardless of the above, this is to mimic the case in production where the application running in gVisor requires more memory than what cgroup allows, and gets OOM-killed. We observed that the sandbox processes |
|
In the attached log, we killed a few threads that detected their stub process had died. We actually need to kill the entire process. |
5c6ea8c to
162de7b
Compare
162de7b to
e7520af
Compare
|
@avagin it works as well! Thanks. I revised the PR as well as the commit message. Could we merge this PR? |
# Introduction When the sandboxed application is killed externally (for example, when it requests more memory than what cgroup allows), the whole sandbox should exit as well. We find this commit 16dba7f#diff-06bbaf439d32bed64b39754ca405a6b8fe4227925bfa92c11428b6ddfc91b962 changed this behavior. This commit led to the fact that when the application is killed, the sandbox is still hanging around. This PR fixes it. # Step to reproduce the hang The hang can be reproduced in any release version including the commit above. Here we use `release-20250319.0` as an example. ## Application: ```go package main import ( "fmt" "time" ) func main() { fmt.Println("Application started") var loop = 0 for { time.Sleep(2 * time.Second) loop++ fmt.Printf("Application is running %d\n", loop) } fmt.Println("Shutting down") } ``` And run this application with gVisor, e.g. `runsc --debug-log=/tmp/runsc/ --debug --strace run test`. Then while the application is running, we kill this process with `sudo kill -9 <pid>` to mimic OOM. Afterwards the sandbox is still hanging. ## runsc command line output ``` Application started Application is running 1 Application is running 2 Application is running 3 Application is running 4 Application is running 5 Application is running 6 Application is running 7 Application is running 8 Application is running 9 ``` Then it gets stuck after the kill command (but does not exit). ## Gvisor log runsc.log.20250327-105656.496989.boot.txt (only the last relevant parts) ``` I0327 10:57:28.770718 1 strace.go:576] [ 2: 6] client E futex(0xc000100148, FUTEX_WAIT|FUTEX_PRIVATE_FLAG, 0x0, null, 0x0, 0x0) I0327 10:57:28.770718 1 strace.go:576] [ 2: 2] client E epoll_pwait(0x3 anon_inode:[eventpoll], 0x7eb16a44c51c {}, 0x80, 0x7cf, null, 0x0) I0327 10:57:28.770740 1 strace.go:614] [ 2: 2] client X epoll_pwait(0x3 anon_inode:[eventpoll], 0x7eb16a44c51c {{events=EPOLLOUT data=[0x65b00001, 0x7ed7610c]}{events=EPOLLOUT data=[0x66b80001, 0x7ed7610c]}}, 0x80, 0x7cf, null, 0x0) = 2 (0x2) (6.004µs) I0327 10:57:28.770767 1 strace.go:576] [ 2: 2] client E epoll_pwait(0x3 anon_inode:[eventpoll], 0x7eb16a44c51c {}, 0x80, 0x7cf, null, 0x0) I0327 10:57:28.770768 1 strace.go:602] [ 2: 3] client X nanosleep(0xc00001ff18 {sec=0 nsec=20000}, null) = 0 (0x0) (62.461µs) I0327 10:57:28.770791 1 strace.go:576] [ 2: 3] client E futex(0x5571c0, FUTEX_WAIT|FUTEX_PRIVATE_FLAG, 0x0, 0xc00001feb8 {sec=1 nsec=999872650}, 0x0, 0x0) I0327 10:57:30.770005 1 strace.go:614] [ 2: 2] client X epoll_pwait(0x3 anon_inode:[eventpoll], 0x7eb16a44c51c {}, 0x80, 0x7cf, null, 0x0) = 0 (0x0) (1.999216401s) I0327 10:57:30.771140 1 strace.go:614] [ 2: 3] client X futex(0x5571c0, FUTEX_WAIT|FUTEX_PRIVATE_FLAG, 0x0, 0xc00001feb8 {sec=1 nsec=999872650}, 0x0, 0x0) = 0 (0x0) errno=110 (connection timed out) (2.000334244s) W0327 10:57:30.780225 1 subprocess_unsafe.go:130] the subprocess 38 exited (status: %!s(unix.WaitStatus=9), err %!s(<nil>)) W0327 10:57:30.780252 1 task_run.go:358] [ 2: 2] Unexpected SwitchToApp error: systrap corrupted memory: subprocess died D0327 10:57:30.780267 1 task_exit.go:215] [ 2: 2] Transitioning from exit state TaskExitNone to TaskExitInitiated D0327 10:57:30.780294 1 task_exit.go:215] [ 2: 2] Transitioning from exit state TaskExitInitiated to TaskExitZombie W0327 10:57:30.781250 1 task_run.go:358] [ 2: 3] Unexpected SwitchToApp error: systrap corrupted memory: subprocess died D0327 10:57:30.781266 1 task_exit.go:215] [ 2: 3] Transitioning from exit state TaskExitNone to TaskExitInitiated D0327 10:57:30.781292 1 task_exit.go:215] [ 2: 3] Transitioning from exit state TaskExitInitiated to TaskExitZombie D0327 10:57:30.781297 1 task_exit.go:215] [ 2: 3] Transitioning from exit state TaskExitZombie to TaskExitDead I0327 10:57:41.715145 1 watchdog.go:294] Watchdog starting loop, tasks: 5, discount: 0s D0327 10:58:04.664761 1 sampler.go:162] Time: Adjusting syscall overhead up to 692 D0327 10:58:08.665378 1 sampler.go:191] Time: Adjusting syscall overhead down to 606 D0327 10:58:09.664941 1 sampler.go:191] Time: Adjusting syscall overhead down to 531 D0327 10:58:10.665540 1 sampler.go:191] Time: Adjusting syscall overhead down to 465 D0327 10:58:11.664765 1 sampler.go:191] Time: Adjusting syscall overhead down to 407 D0327 10:58:15.664958 1 sampler.go:191] Time: Adjusting syscall overhead down to 357 I0327 10:58:26.715574 1 watchdog.go:294] Watchdog starting loop, tasks: 5, discount: 0s D0327 10:58:35.665620 1 sampler.go:191] Time: Adjusting syscall overhead down to 313 ``` `gofer.txt` and `run.txt` do not reveal anything interesting. FUTURE_COPYBARA_INTEGRATE_REVIEW=#11590 from xianzhe-databricks:fix-hang-with-subprocess-death e7520af PiperOrigin-RevId: 741613636
# Introduction When the sandboxed application is killed externally (for example, when it requests more memory than what cgroup allows), the whole sandbox should exit as well. We find this commit 16dba7f#diff-06bbaf439d32bed64b39754ca405a6b8fe4227925bfa92c11428b6ddfc91b962 changed this behavior. This commit led to the fact that when the application is killed, the sandbox is still hanging around. This PR fixes it. # Step to reproduce the hang The hang can be reproduced in any release version including the commit above. Here we use `release-20250319.0` as an example. ## Application: ```go package main import ( "fmt" "time" ) func main() { fmt.Println("Application started") var loop = 0 for { time.Sleep(2 * time.Second) loop++ fmt.Printf("Application is running %d\n", loop) } fmt.Println("Shutting down") } ``` And run this application with gVisor, e.g. `runsc --debug-log=/tmp/runsc/ --debug --strace run test`. Then while the application is running, we kill this process with `sudo kill -9 <pid>` to mimic OOM. Afterwards the sandbox is still hanging. ## runsc command line output ``` Application started Application is running 1 Application is running 2 Application is running 3 Application is running 4 Application is running 5 Application is running 6 Application is running 7 Application is running 8 Application is running 9 ``` Then it gets stuck after the kill command (but does not exit). ## Gvisor log runsc.log.20250327-105656.496989.boot.txt (only the last relevant parts) ``` I0327 10:57:28.770718 1 strace.go:576] [ 2: 6] client E futex(0xc000100148, FUTEX_WAIT|FUTEX_PRIVATE_FLAG, 0x0, null, 0x0, 0x0) I0327 10:57:28.770718 1 strace.go:576] [ 2: 2] client E epoll_pwait(0x3 anon_inode:[eventpoll], 0x7eb16a44c51c {}, 0x80, 0x7cf, null, 0x0) I0327 10:57:28.770740 1 strace.go:614] [ 2: 2] client X epoll_pwait(0x3 anon_inode:[eventpoll], 0x7eb16a44c51c {{events=EPOLLOUT data=[0x65b00001, 0x7ed7610c]}{events=EPOLLOUT data=[0x66b80001, 0x7ed7610c]}}, 0x80, 0x7cf, null, 0x0) = 2 (0x2) (6.004µs) I0327 10:57:28.770767 1 strace.go:576] [ 2: 2] client E epoll_pwait(0x3 anon_inode:[eventpoll], 0x7eb16a44c51c {}, 0x80, 0x7cf, null, 0x0) I0327 10:57:28.770768 1 strace.go:602] [ 2: 3] client X nanosleep(0xc00001ff18 {sec=0 nsec=20000}, null) = 0 (0x0) (62.461µs) I0327 10:57:28.770791 1 strace.go:576] [ 2: 3] client E futex(0x5571c0, FUTEX_WAIT|FUTEX_PRIVATE_FLAG, 0x0, 0xc00001feb8 {sec=1 nsec=999872650}, 0x0, 0x0) I0327 10:57:30.770005 1 strace.go:614] [ 2: 2] client X epoll_pwait(0x3 anon_inode:[eventpoll], 0x7eb16a44c51c {}, 0x80, 0x7cf, null, 0x0) = 0 (0x0) (1.999216401s) I0327 10:57:30.771140 1 strace.go:614] [ 2: 3] client X futex(0x5571c0, FUTEX_WAIT|FUTEX_PRIVATE_FLAG, 0x0, 0xc00001feb8 {sec=1 nsec=999872650}, 0x0, 0x0) = 0 (0x0) errno=110 (connection timed out) (2.000334244s) W0327 10:57:30.780225 1 subprocess_unsafe.go:130] the subprocess 38 exited (status: %!s(unix.WaitStatus=9), err %!s(<nil>)) W0327 10:57:30.780252 1 task_run.go:358] [ 2: 2] Unexpected SwitchToApp error: systrap corrupted memory: subprocess died D0327 10:57:30.780267 1 task_exit.go:215] [ 2: 2] Transitioning from exit state TaskExitNone to TaskExitInitiated D0327 10:57:30.780294 1 task_exit.go:215] [ 2: 2] Transitioning from exit state TaskExitInitiated to TaskExitZombie W0327 10:57:30.781250 1 task_run.go:358] [ 2: 3] Unexpected SwitchToApp error: systrap corrupted memory: subprocess died D0327 10:57:30.781266 1 task_exit.go:215] [ 2: 3] Transitioning from exit state TaskExitNone to TaskExitInitiated D0327 10:57:30.781292 1 task_exit.go:215] [ 2: 3] Transitioning from exit state TaskExitInitiated to TaskExitZombie D0327 10:57:30.781297 1 task_exit.go:215] [ 2: 3] Transitioning from exit state TaskExitZombie to TaskExitDead I0327 10:57:41.715145 1 watchdog.go:294] Watchdog starting loop, tasks: 5, discount: 0s D0327 10:58:04.664761 1 sampler.go:162] Time: Adjusting syscall overhead up to 692 D0327 10:58:08.665378 1 sampler.go:191] Time: Adjusting syscall overhead down to 606 D0327 10:58:09.664941 1 sampler.go:191] Time: Adjusting syscall overhead down to 531 D0327 10:58:10.665540 1 sampler.go:191] Time: Adjusting syscall overhead down to 465 D0327 10:58:11.664765 1 sampler.go:191] Time: Adjusting syscall overhead down to 407 D0327 10:58:15.664958 1 sampler.go:191] Time: Adjusting syscall overhead down to 357 I0327 10:58:26.715574 1 watchdog.go:294] Watchdog starting loop, tasks: 5, discount: 0s D0327 10:58:35.665620 1 sampler.go:191] Time: Adjusting syscall overhead down to 313 ``` `gofer.txt` and `run.txt` do not reveal anything interesting. FUTURE_COPYBARA_INTEGRATE_REVIEW=#11590 from xianzhe-databricks:fix-hang-with-subprocess-death e7520af PiperOrigin-RevId: 741613636
# Introduction When the sandboxed application is killed externally (for example, when it requests more memory than what cgroup allows), the whole sandbox should exit as well. We find this commit 16dba7f#diff-06bbaf439d32bed64b39754ca405a6b8fe4227925bfa92c11428b6ddfc91b962 changed this behavior. This commit led to the fact that when the application is killed, the sandbox is still hanging around. This PR fixes it. # Step to reproduce the hang The hang can be reproduced in any release version including the commit above. Here we use `release-20250319.0` as an example. ## Application: ```go package main import ( "fmt" "time" ) func main() { fmt.Println("Application started") var loop = 0 for { time.Sleep(2 * time.Second) loop++ fmt.Printf("Application is running %d\n", loop) } fmt.Println("Shutting down") } ``` And run this application with gVisor, e.g. `runsc --debug-log=/tmp/runsc/ --debug --strace run test`. Then while the application is running, we kill this process with `sudo kill -9 <pid>` to mimic OOM. Afterwards the sandbox is still hanging. ## runsc command line output ``` Application started Application is running 1 Application is running 2 Application is running 3 Application is running 4 Application is running 5 Application is running 6 Application is running 7 Application is running 8 Application is running 9 ``` Then it gets stuck after the kill command (but does not exit). ## Gvisor log runsc.log.20250327-105656.496989.boot.txt (only the last relevant parts) ``` I0327 10:57:28.770718 1 strace.go:576] [ 2: 6] client E futex(0xc000100148, FUTEX_WAIT|FUTEX_PRIVATE_FLAG, 0x0, null, 0x0, 0x0) I0327 10:57:28.770718 1 strace.go:576] [ 2: 2] client E epoll_pwait(0x3 anon_inode:[eventpoll], 0x7eb16a44c51c {}, 0x80, 0x7cf, null, 0x0) I0327 10:57:28.770740 1 strace.go:614] [ 2: 2] client X epoll_pwait(0x3 anon_inode:[eventpoll], 0x7eb16a44c51c {{events=EPOLLOUT data=[0x65b00001, 0x7ed7610c]}{events=EPOLLOUT data=[0x66b80001, 0x7ed7610c]}}, 0x80, 0x7cf, null, 0x0) = 2 (0x2) (6.004µs) I0327 10:57:28.770767 1 strace.go:576] [ 2: 2] client E epoll_pwait(0x3 anon_inode:[eventpoll], 0x7eb16a44c51c {}, 0x80, 0x7cf, null, 0x0) I0327 10:57:28.770768 1 strace.go:602] [ 2: 3] client X nanosleep(0xc00001ff18 {sec=0 nsec=20000}, null) = 0 (0x0) (62.461µs) I0327 10:57:28.770791 1 strace.go:576] [ 2: 3] client E futex(0x5571c0, FUTEX_WAIT|FUTEX_PRIVATE_FLAG, 0x0, 0xc00001feb8 {sec=1 nsec=999872650}, 0x0, 0x0) I0327 10:57:30.770005 1 strace.go:614] [ 2: 2] client X epoll_pwait(0x3 anon_inode:[eventpoll], 0x7eb16a44c51c {}, 0x80, 0x7cf, null, 0x0) = 0 (0x0) (1.999216401s) I0327 10:57:30.771140 1 strace.go:614] [ 2: 3] client X futex(0x5571c0, FUTEX_WAIT|FUTEX_PRIVATE_FLAG, 0x0, 0xc00001feb8 {sec=1 nsec=999872650}, 0x0, 0x0) = 0 (0x0) errno=110 (connection timed out) (2.000334244s) W0327 10:57:30.780225 1 subprocess_unsafe.go:130] the subprocess 38 exited (status: %!s(unix.WaitStatus=9), err %!s(<nil>)) W0327 10:57:30.780252 1 task_run.go:358] [ 2: 2] Unexpected SwitchToApp error: systrap corrupted memory: subprocess died D0327 10:57:30.780267 1 task_exit.go:215] [ 2: 2] Transitioning from exit state TaskExitNone to TaskExitInitiated D0327 10:57:30.780294 1 task_exit.go:215] [ 2: 2] Transitioning from exit state TaskExitInitiated to TaskExitZombie W0327 10:57:30.781250 1 task_run.go:358] [ 2: 3] Unexpected SwitchToApp error: systrap corrupted memory: subprocess died D0327 10:57:30.781266 1 task_exit.go:215] [ 2: 3] Transitioning from exit state TaskExitNone to TaskExitInitiated D0327 10:57:30.781292 1 task_exit.go:215] [ 2: 3] Transitioning from exit state TaskExitInitiated to TaskExitZombie D0327 10:57:30.781297 1 task_exit.go:215] [ 2: 3] Transitioning from exit state TaskExitZombie to TaskExitDead I0327 10:57:41.715145 1 watchdog.go:294] Watchdog starting loop, tasks: 5, discount: 0s D0327 10:58:04.664761 1 sampler.go:162] Time: Adjusting syscall overhead up to 692 D0327 10:58:08.665378 1 sampler.go:191] Time: Adjusting syscall overhead down to 606 D0327 10:58:09.664941 1 sampler.go:191] Time: Adjusting syscall overhead down to 531 D0327 10:58:10.665540 1 sampler.go:191] Time: Adjusting syscall overhead down to 465 D0327 10:58:11.664765 1 sampler.go:191] Time: Adjusting syscall overhead down to 407 D0327 10:58:15.664958 1 sampler.go:191] Time: Adjusting syscall overhead down to 357 I0327 10:58:26.715574 1 watchdog.go:294] Watchdog starting loop, tasks: 5, discount: 0s D0327 10:58:35.665620 1 sampler.go:191] Time: Adjusting syscall overhead down to 313 ``` `gofer.txt` and `run.txt` do not reveal anything interesting. FUTURE_COPYBARA_INTEGRATE_REVIEW=#11590 from xianzhe-databricks:fix-hang-with-subprocess-death e7520af PiperOrigin-RevId: 741613636
Introduction
When the sandboxed application is killed externally (for example, when it requests more memory than what cgroup allows), the whole sandbox should exit as well. We find this commit 16dba7f#diff-06bbaf439d32bed64b39754ca405a6b8fe4227925bfa92c11428b6ddfc91b962 changed this behavior. This commit led to the fact that when the application is killed, the sandbox is still hanging around.
This PR fixes it.
Step to reproduce the hang
The hang can be reproduced in any release version including the commit above. Here we use
release-20250319.0as an example.Application:
And run this application with gVisor, e.g.
runsc --debug-log=/tmp/runsc/ --debug --strace run test.Then while the application is running, we kill this process with
sudo kill -9 <pid>to mimic OOM. Afterwards the sandbox is still hanging.runsc command line output
Then it gets stuck after the kill command (but does not exit).
Gvisor log
runsc.log.20250327-105656.496989.boot.txt (only the last relevant parts)
gofer.txtandrun.txtdo not reveal anything interesting.