在 Linux 内核中调试 FUSE 死锁( 二 )


# ls /proc/1544450/任务1544450 1544574啊哈,线程组里有两个线程 。其中一个是僵尸,也许另一个不是:
# cat /proc/1544574/stack [<0>] request_wait_answer+0x12f/0x210 [<0>] fuse_simple_request+0x109/0x2c0 [<0>] fuse_flush+0x16f/0x1b0 [<0>] filp_close+0x27/0x70 [< 0>] put_files_struct+0x6b/0xc0 [<0>] do_exit+0x360/0xb80 [<0>] do_group_exit+0x3a/0xa0 [<0>] get_signal+0x140/0x870 [<0>] arch_do_signal_or_restart+0xae/0x7c0 [< 0>] exit_to_user_mode_prepare+0x10f/0x1c0 [<0>] syscall_exit_to_user_mode+0x26/0x40 [<0>] do_syscall_64+0x46/0xb0 [<0>] entry_SYSCALL_64_after_hwframe+0x44/0xae事实上它不是僵尸 。它试图尽可能地成为一个,但由于某种原因它在 FUSE 内部阻塞 。为了找出原因,让我们看一些内核代码 。如果我们查看zap_pid_ns_processes(),它会:
/* * 在我们忽略 SIGCHLD 之前获取我们拥有的 EXIT_ZOMBIE 孩子 。* kernel_wait4() 也将阻塞,直到我们从* parent 命名空间追踪到的孩子被分离并变成 EXIT_DEAD 。*/做{clear_thread_flag(TIF_SIGPENDING);rc = kernel_wait4( -1 , NULL , __WALL, NULL ); } while (rc != -ECHILD);这是我们卡住的地方,但在此之前,它已经完成了:
/* 不允许更多进程进入 pid 命名空间 */ disable_pid_allocation(pid_ns);这就是为什么 docker 不能setns()——


推荐阅读