You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

execv返回错误时如何正确使用waitpid?

问题根源

核心原因:fork继承MySQL连接导致资源冲突

你是在fork循环执行前就创建了MySQL连接对象,fork() 会将父进程的所有资源(包括网络套接字、打开的文件描述符、C++对象实例)复制到子进程空间,MySQL连接使用的TCP套接字是内核级共享对象,父子进程会持有同一个套接字的引用:

  1. 当execv()调用成功时,子进程的整个地址空间会被新的目标程序替换,原程序的C++对象析构逻辑不会执行,继承来的MySQL连接不会被主动关闭,因此父进程的连接不受影响,程序运行正常。
  2. 当execv()调用失败时,子进程会继续运行原程序的逻辑,执行return EXIT_FAILURE退出时,会触发所有继承来的C++对象的析构函数,其中就包括MySQL连接对象的析构,它会直接关闭TCP套接字。此时父进程持有的连接已经被内核标记为关闭,后续操作数据库自然会抛出Lost connection to MySQL server during query错误。

附加逻辑错误

你判断子进程执行结果的代码存在逻辑错误:

if (WIFEXITED(pid_status))
{
    std::cout << "child process exit status: " << WEXITSTATUS(pid_status) << std::endl;
    // 此处错误:WIFEXITED返回非0代表子进程正常退出,你判断它等于0永远不会进入更新分支
    if (WIFEXITED(pid_status) == 0) 
    {
        std::cout << "updating db that file has been loaded: " << files[i].first << std::endl;
    }
}

正确的判断应该是验证子进程的退出码是否为0:if (WEXITSTATUS(pid_status) == 0)。


修复方案

  • 子进程逻辑分支开头第一行先关闭继承自父进程的MySQL连接,该操作只会减少子进程持有的套接字引用计数,不会影响父进程的连接。
  • 禁止在子进程中使用父进程创建的数据库连接,如果你需要在execv失败时子进程写入失败记录,请单独创建新的数据库连接,操作完成后主动关闭再退出子进程。
  • 给MySQL连接的套接字设置FD_CLOEXEC标志,execv执行时会自动关闭该套接字,避免资源泄漏。
  • 修正退出状态判断的逻辑错误。

内容的提问来源于stack exchange,提问作者Siedler

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 03:06:03