打印机应用安装驱动失败问题分析

打印机应用安装驱动失败问题分析

1、问题现象

  打印机管理程序在0.4.9.3的版本下,升级到0.4.9.5的时候,出现打印机安装驱动失败,在故障排查的过程中也出现类似的无法安装的bug。

2、问题分析

  根据ui的提示“安装驱动失败”,应该是调用dbus安装包的接口异常,于是去代码定位到调用dbus安装包附近的代码,查找是否有记录对应的错误日志。代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
QDBusReply<QDBusObjectPath> objPath = interface->call("InstallPackage", "", m_installPackages.join(" "));

if (objPath.isValid()) {
m_jobPath = objPath.value().path();
if (QDBusConnection::systemBus().connect("com.deepin.lastore",
m_jobPath,
"org.freedesktop.DBus.Properties",
"PropertiesChanged",
this, SLOT(propertyChanged(QDBusMessage)))) {
qDebug() << "Start install " << m_installPackages;
return;
} else {
qWarning() << "Connect dbus signal failed";
}
} else {
qWarning() << "DBus error: " << objPath.error().message();
}
&emsp;

&emsp;&emsp;定位到代码之后去日志文件里面查找DBus error:后续输出的具体错误原因。日志输出错误如下:lstat /usr/bin/dde-printer (deleted) no such file or directory。对于这个错误,刚开始以为是dde-printer没有通过白名单验证(DBus的这个安装包的接口需要认证才能调用),后续排查了这个问题。但是在本地二进制存在的情况下,为何报dde-printer不存在?在没有思路的情况下,去虚拟机安装了一个问题iso,通过排除法排除各种干扰因素,最后发现更新完成之后,只要重启了系统,就不会出现这个bug。于是猜测是因为更新了dde-printer二进制程序之后,由于dde-printer一直在后台启动,这时候导致本地程序和内存不一致,所以调用DBus接口时,DBus返回这个错误。

3、验证流程

  1. 在更新完成直接启动程序,查看程序版本

  2. 杀死dde-printer进程,然后重启,再进行安装打印机驱动

    &emsp;结论是更新完成之后,内存中程序版本仍然是旧版本。重启程序之后在进行安装问题就就解决了。

4、解决代码

&emsp;&emsp;解决这个问题,常规办法就是在deb包的postinst脚本中重启程序,但是目前dde-printer程序是用户态自启动的程序。如果通过deb安装完成脚本重启程序,那么程序就会变成root权限。所以采取在postinst脚本中发送自定义信号给程序,然后让程序自己重启。postinst脚本如下:

1
2
3
4
5
6
7
8
9
10
# restart process after updating
ProcessName="dde-printer -m 1" #进程
ID=`ps -ef | grep "$ProcessName" | grep -v "grep" | awk '{print $2}'` #注意此shell脚本的名称,避免自杀
if [ -z "$ID" ];then
echo "process id is empty, process is not existed..."
else
echo "$ID process will restart..."
kill -USR1 $ID #通知进程重启
echo "process has restart..."
fi

&emsp;&emsp;dde-printer重启代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
void handler(int signo)
{
//默认终止的自定义信号,此处作为重启通知
if (signo == SIGUSR1) {
pid_t pid = getpid();
QProcess process;
QString cmd = QString("dde-printer -m 1 -r %1").arg(pid);
process.startDetached(cmd);
}
}

// 绑定SIGUSR1信号
if (signal(SIGUSR1, handler) == SIG_ERR)
{
qWarning("Can't set handler for SIGUSR1\n");
}
if (!DGuiApplicationHelper::setSingleInstance("dde-printer")) {
if (qApp->arguments().contains("-r")) {
//重启模式先kill原始进程
QString originPid = qApp->arguments().at(4).toLocal8Bit();
QProcess process;
QString cmd = "kill";
QStringList args;
args << "-9" << originPid;
process.start(cmd, args);
process.waitForFinished();
qInfo() << "kill origin process " << originPid;
if (!DGuiApplicationHelper::setSingleInstance("dde-printer")) {
qWarning() << "restart process failed";
return -3;
} else {
qInfo() << "restart process success";
}
} else {
qWarning() << "dde-printer is running";
return -2;
}

}


5、小结

&emsp;&emsp;对于后台自启程序,在更新时一定要注意重启的问题,因为更新会改变二进制,或者其它配置配置程序,需要重启才能生效。


打印机应用安装驱动失败问题分析
http://yoursite.com/2021/01/29/打印机安装驱动失败问题分析/
作者
还在输入
发布于
2021年1月29日
许可协议