1. Qt Process 退出码

通过int QProcess::execute(const QString &program, const QStringList &arguments) 启动进程
退出码介绍:
通常情况下,Qt process 使用execute(program, args) 的方式启动一个进程,当这个函数返回时,根据官方文档的介绍,退出码-1, 代表进程崩溃,退出码-2,代表进程启动失败,其他代表进程的退出码,那么,QProcess如何获取的进程的退出码呢?我们来通过一个例子来分析一下QProcess获取进程退出码的过程。
近来,我写了一个demo,通过QProcess启动一个外部进程curl,来下载远程服务器上的资源包,下载失败,返回错误码22,刚开始,不太懂这个22代表什么,这个22从何而来,所以,打开Qt源码,进行跟踪,发现了不少意外收获。
首先,我们进入QProcess::execute(const QString &program, const QStringList &arguments)方法,如图所示:

image.png
如果进程waitForFinished返回false或者进程错误是没有启动,则返回-2,那么,何种情况下会waitForFinished返回false呢?通过分析waitForFinished的实现,如图:image.png
可以只看到,只有当前程序运行状态是没有启动或者没有starting时,返回false,如果我们都不是,则因为我们传入的超时时间时-1,所以会阻塞在这个waitForFinished函数中,直到进程退出,
这时候,如果返回是false,则进程退出,返回退出码-2(进程启动失败)

否则,判断进程是否正常退出,如果是,返回进程的退出码,否则,返回-1(进程意外退出)。
那么,现在问题来了,QProcess如何知道进程的退出码呢?进一步分析exitStatus()函数,如图:
image.png
通过这个函数,我们可以知道,其实,进程的退出码是QProcess对应的d->exitStatus的值,通过Q_D来重定义,这个Q_D其实返回的是QProcessPrivate的对象指针,那么我们返回的exitStatus则是这个QProcessPrivate的成员,
QProcess::ExitStatus exitStatus;
并且,我们可以看到,在waitForFinished,一直一个无限循环中,等待进程退出的信号,通过 windows api
WaitForSingleObject来等待目标进程的信号,而等待线程将会被挂起,消耗很少的cpu,直到进程有信号触发,这函数才会返回WAIT_OBJECT_0, 否则返回超时等,当进程返回WAIT_OBJECT_0时,QProcess读取管道的输出数据,并处理进程的状态,通过findExitCode函数,获取进程的退出码,进而通过windows api GetExitCodeProcess来获取进程的退出码,函数GetExitCodeProcess是获取一个已经中断进程的退出状态。
那么,现在回到我们最开始的问题,QProcess调用execute 启动curl进程返回退出码22,那么可以确定,这个退出码不是QProcess定义的,而是curl进程定义的,通过查询curl资料,发现:
curl退出码.xlsx
根据curl退出码,可以知道,退出码22对应http错误码的400以上的错误码,所以是因为资源在服务器上不存在,所以curl进程下载失败,返回退出码22

总结:

  • 学习使用QProcess::execute启动一个进程,返回退出码:-2 进程启动失败,-1 进程奔溃,其他 启动目标进程的退出码。
  • QProcess通过windows api GetExitCodeProcess来获取进程的退出状态。
  • QProcess通过windows api WaitForSingleObject来等待进程的状态,并且把等待进程挂起。
  • 在我们遇到不清除的问题时,一定要通过源码去跟踪到问题的真实原因。