【2023-03-04】QProcess启动进程后继承父进程fd导致的现场问题

项目场景:

相关背景:

  1. 我方在现场部署了一个主服务应用,暂且记作“MainServer”;
    MainServer的主要作业,是启动一个http服务,提供一个http的接口,接口的绑定端口为1888;
  2. 第三方应用通过调用该接口,通知MainServer启动推流进程,实现将RTSP码流推送到RTMP地址的功能;
  3. 我方提供了一个守护进程,在MainServer异常时,短时间内将应用程序拉起;

问题描述

问题现象:

  1. 在运行一段时间后,调用MainServer的http服务接口,出现接口不再响应的问题。
  2. 通过日志观察发现,在接口不响应之前,提示服务异常,被守护进程重新拉起;
  3. 日志显示,最近的一次拉起动作提示”http 的server端口绑定异常!“;

原因分析:

日志提示中可以看到,端口被绑定,排查过程如下:

  1. 输入命令,查看端口被占用的进程;
netstat -atlnup|grep 1888
  1. 从获取的信息发现,占用的进程为ffmpeg进程,键入命令查询进程信息;
ps -ef|grep ffmpeg
  1. 发现该进程为推流进程,是MainServer启动的;目前由于MainServer被守护进程拉起,所以它的父进程ID变成了1;
  2. 从这个现象,可以分析出,是ffmpeg推流进程占用了1888端口。结论是:

ffmpeg进程本身不会使用1888端口,而它的父进程MainServer会使用;所以ffmpeg是继承了父进程的资源文件描述符,也就是这个socketfd,最终显示占用;

  1. 下面是程序里的代码片段;
 .........................此处省略前置代码................
            if(m_strOutPut.contains("sdp") && m_strOutPut.contains("H264"))
            {
                 qDebug()<<"SelectH264:"<<m_strTransProtocol;
                if(m_strUseAudioFlag == "0"){
                    //不启用音频
                    str<< "-rtsp_transport"<<m_strTransProtocol<<"-i"<<m_rtspurl<<"-an"<<"-vcodec"<<"copy"<<"-f"<<"flv"<<m_rtmpurl;
                }else{
                    //启用音频
                    str<<"-rtsp_transport"<<m_strTransProtocol<<"-i"<<m_rtspurl<<"-acodec"<<"aac"<<"-vcodec"<<"copy"<<"-f"<<"flv"<<m_rtmpurl;
                }

            }
            else if(m_strOutPut.contains("sdp") && m_strOutPut.contains("H265"))
            {
                qDebug()<<"SelectH265:"<<m_strTransProtocol;
                if(m_strUseAudioFlag == "0"){
                    //不启用音频
                    str<< "-rtsp_transport"<<m_strTransProtocol<<"-i"<<m_rtspurl<<"-an"<<"-vcodec"<<"libopenh264"<<"-f"<<"flv"<<m_rtmpurl;
                }else{
                    //启用音频
                    str<<"-rtsp_transport"<<m_strTransProtocol<<"-i"<<m_rtspurl<<"-acodec"<<"aac"<<"-vcodec"<<"libopenh264"<<"-f"<<"flv"<<m_rtmpurl;
                }                                                    
            }else {
                qDebug()<<"Select Default:"<<m_strTransProtocol;
                if(m_strUseAudioFlag == "0"){
                    //不启用音频
                    str<< "-rtsp_transport"<<m_strTransProtocol<<"-i"<<m_rtspurl<<"-an"<<"-vcodec"<<"copy"<<"-f"<<"flv"<<m_rtmpurl;
                }else{
                    //启用音频
                    str<<"-rtsp_transport"<<m_strTransProtocol<<"-i"<<m_rtspurl<<"-acodec"<<"aac"<<"-vcodec"<<"copy"<<"-f"<<"flv"<<m_rtmpurl;
                }
            }
            m_process->start(QCoreApplication::instance()->applicationDirPath()+"/ffmpeg",str);
        }  
        m_bRun = true;
        while(m_bRun){
            if(m_process->waitForFinished()){
                msg = QString("%1:killed self!").arg(m_strTimeflag);
                WriteTransLog(msg);
            }
            usleep(10);
        }


解决方案:

至此,真相大白;守护脚本中,如果检测到进程消失了,需要拉起来,则执行下面两步骤:

  1. 结束ffmpeg系列进程
  2. 拉起MainServer主进程

总结:
实际上,在Linux系统上,父进程创建子进程时需要注意资源的继承,本场景中,socket文件描述符就是其中一个。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ShaYQ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值