mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Report task exit in /proc/[pid]/{stat,status} before task goroutine exit.
Between when runExitNotify.execute() returns nil (indicating that the task goroutine should exit) and when Task.run() advances Task.gosched.State to TaskGoroutineNonexistent (indicating that the task goroutine is exiting), there is a race window in which the Task is waitable (since TaskSet.mu is unlocked and Task.exitParentNotified is true) but will be reported by /proc/[pid]/status as running. Close the window by checking Task.exitState before task goroutine exit. PiperOrigin-RevId: 378711484
This commit is contained in:
@@ -536,7 +536,7 @@ func (tg *ThreadGroup) updateCPUTimersEnabledLocked() {
|
||||
// appropriate for /proc/[pid]/status.
|
||||
func (t *Task) StateStatus() string {
|
||||
switch s := t.TaskGoroutineSchedInfo().State; s {
|
||||
case TaskGoroutineNonexistent:
|
||||
case TaskGoroutineNonexistent, TaskGoroutineRunningSys:
|
||||
t.tg.pidns.owner.mu.RLock()
|
||||
defer t.tg.pidns.owner.mu.RUnlock()
|
||||
switch t.exitState {
|
||||
@@ -546,16 +546,16 @@ func (t *Task) StateStatus() string {
|
||||
return "X (dead)"
|
||||
default:
|
||||
// The task goroutine can't exit before passing through
|
||||
// runExitNotify, so this indicates that the task has been created,
|
||||
// but the task goroutine hasn't yet started. The Linux equivalent
|
||||
// is struct task_struct::state == TASK_NEW
|
||||
// runExitNotify, so if s == TaskGoroutineNonexistent, the task has
|
||||
// been created but the task goroutine hasn't yet started. The
|
||||
// Linux equivalent is struct task_struct::state == TASK_NEW
|
||||
// (kernel/fork.c:copy_process() =>
|
||||
// kernel/sched/core.c:sched_fork()), but the TASK_NEW bit is
|
||||
// masked out by TASK_REPORT for /proc/[pid]/status, leaving only
|
||||
// TASK_RUNNING.
|
||||
return "R (running)"
|
||||
}
|
||||
case TaskGoroutineRunningSys, TaskGoroutineRunningApp:
|
||||
case TaskGoroutineRunningApp:
|
||||
return "R (running)"
|
||||
case TaskGoroutineBlockedInterruptible:
|
||||
return "S (sleeping)"
|
||||
|
||||
Reference in New Issue
Block a user