一个QT程序无法启动问题的分析与解决

最近调试设备,遇到了一个奇怪的问题:QT程序无法重启。

查看日志,发现报如下错误:

QLock::QLock: Cannot create semaphore /tmp/qtembedded-0/QtEmbedded-0 'd' (22, Invalid argument)
Cannot get display lock
Aborted

下面整理记录问题的解决过程。

1 首先,说明程序之前奔溃了。
因为这是重启过程中报的信息。后台监控发现程序奔溃后,会再次拉起。这个日志就是拉起过程中出现的。

2 先不管之前为啥崩溃了。我们看看程序为啥无法成功重启。

3 是否是因为程序本身出了什么问题?
因为这个错误之前不曾见过,又因为之前出现过flash上的文件发生损坏的情况,所以猜测会不会是因为坏块导致的执行程序文件损坏。
通过将程序二进制文件拷贝出来以及将新的替换进去,验证程序没有发生变化,但是问题一直存在。
使用其他QT程序,问题也依然存在,所以程序本身的问题被排除

4 是否是因为QT基础库问题导致?
基本思路还是跟3中描述一样,只不过这次怀疑是否是QT的基础库发生了变动。
如果基础库发生变动,那么所有QT程序都可能无法正常运行。
将设备上的QT相关库拷贝出来,跟烧写版本对比,发现基础库没有变化。
重新替换QT基础库,问题仍然存在。

5 是否是因为QT运行环境问题导致?
拷贝异常设备中,root tmp等目录下QT生成的文件,跟正常设备对比,发现没有明显的差异

6 查找错误日志所在代码
既然前面几个怀疑点都排除了,没有明确的验证方向的情况下,决定看看错误日志到底是那块代码打印的。
通过搜索QT程序和QT开发环境,发现Cannot get display lock这一句是QT基础库里的打印
进一步的,确定了代码所在位置:qtapplication_qws.cpp.

跟踪代码,发现是qtlock初始化失败了。
但是,相关的代码有很多编译选项,不确定错误到底是那个if else逻辑出来的。
考虑到整个QT自身的代码比较庞大,搜索也不容易确定宏是否是打开状态,决定添加日志,跟踪定位问题。

7 重新编译QT库
重新编译QT库后,将日志所在的GUI库替换,重新跑程序来看:
 

   QLock::lock(): file name /tmp/qtembedded-0/QtEmbedded-0 id=d create=create QLock::lock(): QT_POSIX_IPC QLock::lock(): QT_POSIX_IPC 1 data id = -1 semkey=1678592551 (2, No such file or directory)QLock::lock(): QT_POSIX_IPC 2 data id = -1 semkey=1678592551, (28, No space left on device)QLock::lock(): QT_POSIX_IPC 3 data id = -1 arg.val=200, (22, Invalid argument)QLock::QLock: Cannot create semaphore /tmp/qtembedded-0/QtEmbedded-0 'd' (22, Invalid argument)Cannot get display lockAborted

这是最后确定问题的日志,中间过程不再说明。
我们看到,走了IPC处理分支
关键错误在第四行,errno是28,说明没有空间
这句日志对应的代码接口为semget

8 查看系统调用说明
man semget,查看这个系统调用的使用说明。
其中有关于28错误的说明,ENOSPC,基本是说创建信号量时,达到了系统配置的上限,没有空间创建新的。
到这里,基本可以猜出问题所在了。就是程序之前可能反复重启,消耗了所有的信号量空间,达到一定次数后,无法创建新的信号量,导致启动失败。

9 查看系统配置参数
查看系统对信号量 共享内存等的配置
 # cat /proc/sys/kernel/sem 
  250     32000   32      128

可以看到,信号量给的是128个。
具体查看系统中创建的信号量

  # cat /proc/sysvipc/sem key      semid perms      nsems   uid   gid  cuid  cgid      otime      ctime1678576641      32768   600          1     0     0     0     0 1649596772         431678623274      65537   600          1     0     0     0     0 1649596832 16495967741678624879    4259842   600          1     0     0     0     0 1649606005 16496059371678625856     131075   600          1     0     0     0     0 1649596973 1649596905...1678593752    4030586   600          1     0     0     0     0 1649604774 16496047071678595070    4063355   600          1     0     0     0     0 1649604848 16496047761678596881    4096124   600          1     0     0     0     0 1649604917 16496048491678598116    4128893   600          1     0     0     0     0 1649604986 16496049181678599937    4161662   600          1     0     0     0     0 1649605054 16496049871678598220    4358271   600          1     0     0     0     0 1649964888 1649964880

统计一下,发现达到了上限。这里多的1是第一行,用于说明各个列段含义的行
  # cat /proc/sysvipc/sem  | wc -l
  129

10 验证
删除一个信号量,重启程序,可以看到重启成功

# ipcrm -s 4194431

  QLock::lock():  file name /tmp/qtembedded-0/QtEmbedded-0 id=d create=create QLock::lock(): QT_POSIX_IPC QLock::lock(): QT_POSIX_IPC 1 data id = -1 semkey=1678598220 (2, No such file or directory)QLock::lock(): QT_POSIX_IPC 2 data id = 4358271 semkey=1678598220, (2, No such file or directory)QLock::lock(): QT_POSIX_IPC 3 data id = 4358271 arg.val=200, (2, No such file or directory)

关闭程序,再次重启,看到失败,说明问题就是由于空间限制,导致信号量创建失败产生

  QLock::lock():  file name /tmp/qtembedded-0/QtEmbedded-0 id=d create=create QLock::lock(): QT_POSIX_IPC QLock::lock(): QT_POSIX_IPC 1 data id = -1 semkey=1678598276 (2, No such file or directory)QLock::lock(): QT_POSIX_IPC 2 data id = -1 semkey=1678598276, (28, No space left on device)QLock::lock(): QT_POSIX_IPC 3 data id = -1 arg.val=200, (22, Invalid argument)QLock::QLock: Cannot create semaphore /tmp/qtembedded-0/QtEmbedded-0 'd' (22, Invalid argument)Cannot get display lockAborted

11 进一步的研究
根据代码来看,每次创建信号量的ftok函数调用参数都是一样的,但是为啥QT每次打印出来的id不一样呢。
因为不一样,所以每次创建的总是保留着,直到空间用完。
  
但是根据接口说明,ftok同样的参数,生成的结果是一样的。专门写了一个程序验证了一下:
  /tmp # /mnt/a.out 
  semkey is 1678611420 
  /tmp # /mnt/a.out 
  semkey is 1678611420 
  /tmp # /mnt/a.out 
  semkey is 1678611420 
  
为啥QT创建的不一样呢?
我们重新创建文件,再跑程序,可以看到生成的不一样了。
ftok是根据的文件的inode信息来生成id的。
  /tmp # rm /tmp/qtembedded-0/QtEmbedded-0
  /tmp # touch /tmp/qtembedded-0/QtEmbedded-0
  /tmp # /mnt/a.out 
  semkey is 1678611403 
  
因此,QT里是每次新建了文件导致id不一样了。对此做针对性修改,问题即解决。

12:其他

涉及的代码文件为:
qt-everywhere-opensource-src\src\gui\kernel\qappliction_qws.cpp
qt-everywhere-opensource-src\src\gui\embedded\qlock.cpp

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/130063.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

axios 实现请求重试

前景提要: ts 简易封装 axios,统一 API 实现在 config 中配置开关拦截器 请求重试的核心是可以重放请求,具体实现就是在 axios 中,拿到当前请求的 config 对象,再用 axios 实例,就能重放请求。 在无感刷新…

【WinForm详细教程七】WinForm中的DataGridView控件

文章目录 1.主要属性DataSource行(Row 相关属性)列(Column 相关属性)单元格(Cell 相关属性)逻辑删除AllowUserToAddRowsAllowUserToDeleteRowsAllowUserToOrderColumns其他布局和行为属性 2.控件中的行、列…

PHP foreach 循环跳过本次循环

$a [[id>1],[id>2],[id>3],[id>4],[id>5],[id>6],[id>7],[id>18],];foreach($a as $v){if($v[id] 5){continue;}$b[] $v[id];}return show_data(,$b); 结果:

ASTM F963-23美国玩具安全新标准发布

新标准发布 2023年10月13日,美国材料与试验协会(ASTM)发布了新版玩具安全标准ASTM F963-23。 主要更新内容 与ASTM F963-17相比,此次更新包括:单独描述了基材重金属元素的豁免情况,更新了邻苯二甲酸酯的管控…

Android.bp探究

有时不知道Android.bp要咋写,特意看了下源码: ./build/soong/androidmk/androidmk/android.go 简单的Android.bp的模板是下面这个样子: [module type] {name: "[name value]",[property1 name]:"[property1 val…

上班族必备:制作电子宣传册的网站

​对于上班族来说,制作电子宣传册是一项非常重要的技能。因为宣传册是展示公司形象、产品特点、服务优势的重要工具,也是与客户沟通交流的重要手段。那么,如何制作一份高质量的电子宣传册呢?今天就为大家推荐几个制作电子宣传册的…

腾讯云向量数据库正式对外全量开放公测

11月1日,腾讯云对外宣布向量数据库正式全量开放公测,同时性能层面带来巨大提升。腾讯云数据库副总经理罗云表示,除了公测之外,腾讯云向量数据库单索引已经支持百亿级向量规模,支持百万级QPS毫秒级查询延迟,…

如何让 Bean 深度感知 Spring 容器

Spring 有一个特点,就是创建出来的 Bean 对容器是无感的,一个 Bean 是怎么样被容器从一个 Class 整成一个 Bean 的,对于 Bean 本身来说是不知道的,当然也不需要知道,也就是 Bean 对容器的存在是无感的。 但是有时候我…

【PHP】对称加密算法 AES-256-GCM 代码示例

前言 下面介绍在PHP代码中,如何对数据进行 AES-256-GCM 加密和解密。我们可以使用 openssl 和 sodium 扩展来实现加密,它们都支持 AES-256-GCM 算法,下面将给出两种扩展的代码示例。 注:在对称加密算法中,除了应用广泛…

【ChatGLM2-6B】P-Tuning训练微调

机器配置 阿里云GPU规格ecs.gn6i-c4g1.xlargeNVIDIA T4显卡*1GPU显存16G*1 准备训练数据 进入/ChatGLM-6B/ptuningmkdir AdvertiseGencd AdvertiseGen上传 dev.json 和 train.json内容都是 {"content": "你是谁", "summary": "你好&…

【代码随想录】算法训练计划11

1、20. 有效的括号 题目: 给定一个只包括 ‘(’,‘)’,‘{’,‘}’,‘[’,‘]’ 的字符串 s ,判断字符串是否有效。 有效字符串需满足: 左括号必须用相同类型的右括号闭合。 左括号…

AI:53-基于机器学习的字母识别

🚀 本文选自专栏:AI领域专栏 从基础到实践,深入了解算法、案例和最新趋势。无论你是初学者还是经验丰富的数据科学家,通过案例和项目实践,掌握核心概念和实用技能。每篇案例都包含代码实例,详细讲解供大家学习。 📌📌📌本专栏包含以下学习方向: 机器学习、深度学…

推荐PHP付费进群源码

PHP付费进群源码带自动定位基于ThinkPHP框架开发的,可以快速搭建知识付费粉丝进群。 更新: 1.首页付款轮播 2.城市定位功能 3.更新及优化域名库及支付设置 4.新增一张图模板设置模式,简化后台模板设置 5.前后台其他优化 演示地址&#xff1a…

使用navicat操纵数据库

<1>连接数据库 打开Navicat&#xff0c;点击“连接”&#xff0c;选择“MySQL”&#xff0c;这边是本机安装的mysql,主机为localhost&#xff0c;输入root密码。 使用Navicat创建数据库并导入SQL文件 SQL查询 普通SQL查询 USE demo; SELECT * FROM t_emp;SELECT emp…

动态内存malloc,calloc,realloc如何使用,使用场景及使用free释放内存时崩溃的原因

目录 1.内存区域 2.void与void* 3.应用场景 4.malloc 5.calloc 6.realloc 7.free崩溃的原因 7.1引入 7.2具体原因 7.2.1越界 7.2.2指针移动 7.2.3重复释放同一段内存 1.内存区域 局部变量:定义在函数内部的变量,包括形参,在栈(stack)中,作用域在函数内部有效,生存周…

【缓存】Spring全家桶中@CacheEvict无效情况共有以下几种

Spring全家桶中CacheEvict无效情况共有以下几种 一、背景介绍二、原因分析三、解决方案 一、背景介绍 SpringBoot中使用Cacheable注解缓存数据&#xff0c;使用CacheEvict注解删除缓存。但是在项目使用过程中&#xff0c;发现使用CacheEvict注解删除缓存无效。 拓展&#xff…

Redis那些事儿(一)

说到redis大家都不陌生&#xff0c;其中包括&#xff1a;共有16个数据库&#xff0c;默认为第0个数据库&#xff1b;数据以key-value键值的形式存储&#xff1b;数据类型包括String、List、Hash、Set等&#xff0c;其中最常用的是字符串&#xff1b;是单线程的、基于内存的&…

腾讯云优惠券是什么?腾讯云优惠券怎么领取?

腾讯云是腾讯集团倾力打造的云计算品牌&#xff0c;为了吸引用户上云&#xff0c;经常推出各种优惠活动&#xff0c;其中就包括腾讯云优惠券。 1、腾讯云优惠券解释说明 腾讯云优惠券是腾讯云的一种优惠凭证&#xff0c;包括代金券和折扣券&#xff0c;领券之后新购、续费、升…

AD9371 官方例程裸机SW 和 HDL配置概述(三)

AD9371 系列快速入口 AD9371ZCU102 移植到 ZCU106 &#xff1a; AD9371 官方例程构建及单音信号收发 ad9371_tx_jesd -->util_ad9371_xcvr接口映射&#xff1a; AD9371 官方例程之 tx_jesd 与 xcvr接口映射 AD9371 官方例程 时钟间的关系与生成 &#xff1a; AD9371 官方…

前端之jQuery

目录 一、jQuery jQuery内容 jQuery版本 jQuery对象 jQuery基础语法 二、查找标签 基本选择器 层级选择器 基本筛选器 属性选择器 表单筛选器 三、筛选器方法 四、操作标签 一、jQuery jQuery是一个轻量级的、兼容多浏览器的JavaScript库。jQuery使用户能够更方便…