最近調(diào)試設(shè)備,遇到了一個奇怪的問題:QT程序無法重啟。
查看日志,發(fā)現(xiàn)報如下錯誤:
QLock::QLock: Cannot create semaphore /tmp/qtembedded-0/QtEmbedded-0 'd' (22, Invalid argument)
Cannot get display lock
Aborted
下面整理記錄問題的解決過程。
1 首先,說明程序之前奔潰了。
因為這是重啟過程中報的信息。后臺監(jiān)控發(fā)現(xiàn)程序奔潰后,會再次拉起。這個日志就是拉起過程中出現(xiàn)的。
2 先不管之前為啥崩潰了。我們看看程序為啥無法成功重啟。
3 是否是因為程序本身出了什么問題?
因為這個錯誤之前不曾見過,又因為之前出現(xiàn)過flash上的文件發(fā)生損壞的情況,所以猜測會不會是因為壞塊導(dǎo)致的執(zhí)行程序文件損壞。
通過將程序二進制文件拷貝出來以及將新的替換進去,驗證程序沒有發(fā)生變化,但是問題一直存在。
使用其他QT程序,問題也依然存在,所以程序本身的問題被排除
4 是否是因為QT基礎(chǔ)庫問題導(dǎo)致?
基本思路還是跟3中描述一樣,只不過這次懷疑是否是QT的基礎(chǔ)庫發(fā)生了變動。
如果基礎(chǔ)庫發(fā)生變動,那么所有QT程序都可能無法正常運行。
將設(shè)備上的QT相關(guān)庫拷貝出來,跟燒寫版本對比,發(fā)現(xiàn)基礎(chǔ)庫沒有變化。
重新替換QT基礎(chǔ)庫,問題仍然存在。
5 是否是因為QT運行環(huán)境問題導(dǎo)致?
拷貝異常設(shè)備中,root tmp等目錄下QT生成的文件,跟正常設(shè)備對比,發(fā)現(xiàn)沒有明顯的差異
6 查找錯誤日志所在代碼
既然前面幾個懷疑點都排除了,沒有明確的驗證方向的情況下,決定看看錯誤日志到底是那塊代碼打印的。
通過搜索QT程序和QT開發(fā)環(huán)境,發(fā)現(xiàn)Cannot get display lock這一句是QT基礎(chǔ)庫里的打印
進一步的,確定了代碼所在位置:qtapplication_qws.cpp.
跟蹤代碼,發(fā)現(xiàn)是qtlock初始化失敗了。
但是,相關(guān)的代碼有很多編譯選項,不確定錯誤到底是那個if else邏輯出來的。
考慮到整個QT自身的代碼比較龐大,搜索也不容易確定宏是否是打開狀態(tài),決定添加日志,跟蹤定位問題。
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 lock
Aborted
這是最后確定問題的日志,中間過程不再說明。
我們看到,走了IPC處理分支
關(guān)鍵錯誤在第四行,errno是28,說明沒有空間
這句日志對應(yīng)的代碼接口為semget
8 查看系統(tǒng)調(diào)用說明
man semget,查看這個系統(tǒng)調(diào)用的使用說明。
其中有關(guān)于28錯誤的說明,ENOSPC,基本是說創(chuàng)建信號量時,達到了系統(tǒng)配置的上限,沒有空間創(chuàng)建新的。
到這里,基本可以猜出問題所在了。就是程序之前可能反復(fù)重啟,消耗了所有的信號量空間,達到一定次數(shù)后,無法創(chuàng)建新的信號量,導(dǎo)致啟動失敗。
9 查看系統(tǒng)配置參數(shù)
查看系統(tǒng)對信號量 共享內(nèi)存等的配置
?# cat /proc/sys/kernel/sem?
? 250 ? ? 32000 ? 32 ? ? ?128
可以看到,信號量給的是128個。
具體查看系統(tǒng)中創(chuàng)建的信號量
# cat /proc/sysvipc/sem
key semid perms nsems uid gid cuid cgid otime ctime
1678576641 32768 600 1 0 0 0 0 1649596772 43
1678623274 65537 600 1 0 0 0 0 1649596832 1649596774
1678624879 4259842 600 1 0 0 0 0 1649606005 1649605937
1678625856 131075 600 1 0 0 0 0 1649596973 1649596905
...
1678593752 4030586 600 1 0 0 0 0 1649604774 1649604707
1678595070 4063355 600 1 0 0 0 0 1649604848 1649604776
1678596881 4096124 600 1 0 0 0 0 1649604917 1649604849
1678598116 4128893 600 1 0 0 0 0 1649604986 1649604918
1678599937 4161662 600 1 0 0 0 0 1649605054 1649604987
1678598220 4358271 600 1 0 0 0 0 1649964888 1649964880
統(tǒng)計一下,發(fā)現(xiàn)達到了上限。這里多的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)
關(guān)閉程序,再次重啟,看到失敗,說明問題就是由于空間限制,導(dǎo)致信號量創(chuàng)建失敗產(chǎn)生
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 lock
Aborted
11 進一步的研究
根據(jù)代碼來看,每次創(chuàng)建信號量的ftok函數(shù)調(diào)用參數(shù)都是一樣的,但是為啥QT每次打印出來的id不一樣呢。
因為不一樣,所以每次創(chuàng)建的總是保留著,直到空間用完。
??
但是根據(jù)接口說明,ftok同樣的參數(shù),生成的結(jié)果是一樣的。專門寫了一個程序驗證了一下:
? /tmp # /mnt/a.out?
? semkey is 1678611420?
? /tmp # /mnt/a.out?
? semkey is 1678611420?
? /tmp # /mnt/a.out?
? semkey is 1678611420?
??
為啥QT創(chuàng)建的不一樣呢?
我們重新創(chuàng)建文件,再跑程序,可以看到生成的不一樣了。
ftok是根據(jù)的文件的inode信息來生成id的。
? /tmp # rm /tmp/qtembedded-0/QtEmbedded-0
? /tmp # touch /tmp/qtembedded-0/QtEmbedded-0
? /tmp # /mnt/a.out?
? semkey is 1678611403?
??
因此,QT里是每次新建了文件導(dǎo)致id不一樣了。對此做針對性修改,問題即解決。
12:其他文章來源:http://www.zghlxwxcb.cn/news/detail-744060.html
涉及的代碼文件為:
qt-everywhere-opensource-src\src\gui\kernel\qappliction_qws.cpp
qt-everywhere-opensource-src\src\gui\embedded\qlock.cpp文章來源地址http://www.zghlxwxcb.cn/news/detail-744060.html
到了這里,關(guān)于一個QT程序無法啟動問題的分析與解決的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!