---
title: fork方式创建子进程导致应用进程卡死-昇腾社区
description: 多卡训练场景下，出现训练进程卡死，或者出现训练超时、用户DataLoader卡死等现象。
keywords: 方式创建子进,程导致应用进,程卡死,昇腾社区,问题现象描述,原因分析,将指定进程的,堆栈信息导出
url: https://www.hiascend.com/document/caselibrary/detail/ptacase_0050
section: (其他)
---

# fork方式创建子进程导致应用进程卡死-昇腾社区

URL: https://www.hiascend.com/document/caselibrary/detail/ptacase_0050
描述: 多卡训练场景下，出现训练进程卡死，或者出现训练超时、用户DataLoader卡死等现象。
关键词: 方式创建子进,程导致应用进,程卡死,昇腾社区,问题现象描述,原因分析,将指定进程的,堆栈信息导出

昇腾文档 [了解详情](https://www.hiascend.com/document)

故障案例 [了解详情](https://www.hiascend.com/document/caselibrary)

fork方式创建子进程导致应用进程卡死

fork方式创建子进程导致应用进程卡死

2025/03/18

883

问题信息

| 问题来源 | 产品大类 | 产品子类 | 关键字 |
| --- | --- | --- | ---|
| 官方 | 模型训练 | PyTorch | -- |

#### 问题现象描述

多卡训练场景下，出现训练进程卡死，或者出现训练超时、用户DataLoader卡死等现象。

#### 原因分析

1. 查看Python堆栈，堆栈信息中包含fork关键字。

使用pyspy工具查看Python堆栈信息的命令示例如下。

使用pyspy命令前，需要安装gdb和py-spy。若环境中未安装gdb，可通过包管理（如apt-get install gdb命令、yum install gdb命令）进行安装，详细安装步骤及使用方法请参见GDB官方文档 [了解详情](https://sourceware.org/gdb/)；若环境中未安装py-spy，可使用pip3 install py-spy命令安装（若安装时提示pip版本低，例如You are using pip version 19.2.3, however version 24.0 is available，这时可按照提示使用pip3 install --upgrade pip命令升级pip即可）。

```
# 将指定进程的堆栈信息导出到指定文件中，pid表示卡住的用户进程ID，pyspy.log表示存放堆栈信息的文件，请根据实际情况替换
py-spy dump -p pid > pyspy.log
```

堆栈信息示例如下（xxxx表示目录名称、trainApp表示训练程序，由实际业务情况决定，此处仅为示例）：

```
1 Process 16203: /train/xxxx/xxxx/xxxx/python3.8 -u -m trainApp --config-dir
2 Python  v3.8.19 (/train/xxxx/xxxx/xxxx/python3.8)
3
4 Thread 0xFFFF9CF35B50 (active): "MainThread"
5    poll (multiprocessing/popen_fork.py:27)
6    wait (multiprocessing/popen_fork.py:47)
7    join (multiprocessing/process.py:149)
8    _terminate_pool (multiprocessing/pool.py:729)
9    __call__ (multiprocessing/util.py:224)
10   _scale_down_hw (datasets/datasets.py:96)
11   __init__ (datasets/datasets.py:73)
......
```
2. 查看C/C++堆栈，堆栈信息中包含acquire_lock关键字。

通过gdb命令观察卡住进程的调用栈信息，若环境中未安装gdb，则需要安装gdb，可通过包管理（如apt-get install gdb、yum install gdb）进行安装，详细安装步骤及使用方法请参见GDB官方文档 [了解详情](https://sourceware.org/gdb/)。

```
# 先执行gdb命令,pid表示卡住的用户进程ID，请根据实际情况替换
gdb -p pid
# 再查看调用栈
(gdb)bt
```

堆栈信息示例如下：

```
#0 0x0000ffffa9b2b268 in do_futex_wait.constprop () from /lib/aarch64-linux-gnu/libpthread.so.0
#1 0x0000ffffa9b2b39c in   new_sem_waut_slow.constprop.0 () from /lib/aarch64-linux-gnu/libpthread.so.0
#2 0x0000ffffa9e96eb8 in PyThread_acquire_lock_timed () from /usr/local/lib/libpython3.8.so.1.0
#3 0x0000ffffa9e865a8 in _PyThreadState_DeleteExcept () from /usr/local/lib/libpython3.8.so.1.0
#4 0x0000ffffa9eb94ac in _PyOS_AtferFork_Child () from /usr/local/lib/libpython3.8.so.1.0
#5 0x0000ffffa9eb9638 in ?? () from /usr/local/lib/libpython3.8.so.1.0
......
```
3. 通过Python堆栈的fork关键字以及C++堆栈的acquire_lock关键字，确认训练进程卡死是因为用fork方式启进程触发Python的bug而导致的问题。

在Python3.8~Python3.11版本中如果不指定创建进程的方式，或者显式指定为fork时，在创建子进程时可能会复制主进程的锁状态，而在子进程里再触发获取锁时，就会导致死锁，进而导致业务进程卡死。

Python社区有相同问题的issue：https://github.com/python/cpython/issues/74580 [了解详情](https://github.com/python/cpython/issues/74580)。

#### 解决措施

两种解决方式，由用户根据业务情况选用：

- 方式一：按照Python官网 [了解详情](https://www.python.org/downloads/)的指导，升级Python3.8~Python3.11版本的补丁。

在Python官网，针对Python3.8~Python3.11版本都出了补丁版本，解决fork方式引起的bug。

在这些补丁版本中，也有针对fork问题的相应说明，如下：
- 方式二：修改客户业务代码，显示使用forkserver或者spawn方式。

注意事项：如果涉及修改fork的地方比较多的或工作量比较大，建议采用方式一，防止修改遗漏。

1. 找到Python安装目录

执行pip show torch命令查找Python安装目录，查询结果示例如下：
2. 在Python安装目录下执行find -name popen_fork.py命令找到popen_fork.py文件，在fork起进程的地方增加都触发堆栈的代码。

在_launch(self,process_obj)函数内添加代码，目的是走fork的子进程都触发堆栈：

例如，在上图70行的位置增加如下代码，用于在fork启进程的地方触发堆栈消息打印：

```
import traceback
import  time
timestamp = time.time()
timestamp_str = str(int(timestamp))
file_name = f"stack_{timestamp_str}.txt"
with open("/home/{}.txt".format(file_name),"a") as f:
    traceback.print_stack(file=f)
```
3. 复跑训练业务，再次查看Python堆栈。

在堆栈信息中，先忽略CANN相关的堆栈，只要修改客户业务的fork，切换为“spawn”或“forkserver”启动方式。关于启动方式的详细使用说明，请参见Python官网文档 [了解详情](https://docs.python.org/zh-cn/3.8/library/multiprocessing.html)（此处可根据所用的Python版本，选择对应版本的文档）。

本页内容

- 问题信息
- 问题现象描述
- 原因分析
- 解决措施
