程序测试环境是:slackware系统,属于linux系统,有桌面(Xface Session)。系统镜像是:slackware64-15.0-install-dvd.iso。qt、c++代码实现。
问题描述:延续上一篇文章,将wps软件窗口内嵌到qt的窗口后,出现一个棘手的问题,就是无法正常的关闭wps进程,即使表面上关闭了,再次打开并内嵌到主窗口时,会出现打不开wps软件的问题,会发现有wps的僵尸进程。
必要条件:slackware系统里需要安装wps、qt5开发工具,本篇文章不做详述。
程序编译:编译还是和上一篇文章保持一致。
我直接说问题的原因,当我们通过fork打开wps软件时,linux系统会出现两个关于该软件的wps进程(wpspdf),通过linux命令查看下进程信息如下:
/office6/wpspdf 这个进程就是打开pdf文件的软件wpspdf进程。
/bin/bash/ 这个进程是wpspdf进程的父进程。qt主窗口创建该进程,该进程又创建打开pdf的进程。
这俩进程都必须正常退出,才能保证我们下一次正确的再次打开软件。
第一种情况:当我们关闭了wps的qt父窗口,而不关闭wps软件界面(比如通过wps右上角的那个关闭按钮)时,虽然wps软件界面没了,但是后台的两个进程都没有关闭,这就导致wps的软件进程处于一种异常状态,这就导致下次打开时,发现完全打不开软件了。
第二种情况:如上图,当我们关闭了wps软件(比如通过wps右上角的那个关闭按钮),也关闭了其qt父窗口,这时我们linux命令查看进程信息会发现,wps进程剩了一个,而且还是个僵尸进程。其实就是/bin/bash/ 那个进程变成了僵尸进程。主要原因就是我们qt主窗口在创建该进程时,我们没有做wait操作,所以该进程没有正常退出,成为了僵尸进程。(上面两张图的进程号不一样的原因是,这是两次测试,所以id值不一样)。
以下是我修改后的最终代码:
form.h
#ifndef FORM_H
#define FORM_H
#include <QWidget>
#include <QProcess>
namespace Ui {
class Form;
}
class Form : public QWidget
{
Q_OBJECT
public:
explicit Form(QWidget *parent = nullptr);
~Form();
void open_wps();
static void open_wps_thread();
void close_wps();
void close_wps2();
void find_window_id_in_tree();
void find_window_id_by_class();
void add_window_in_qt();
private:
Ui::Form *ui;
QProcess *process;
uint32_t window_id;
};
#endif // FORM_H
form.cpp
#include "form.h"
#include "ui_form.h"
#include <QWindow>
#include <QVBoxLayout>
#include <QtX11Extr