我一生中, 遇過許多難纏的bug, 但沒有一個像這次碰到的, 那麼令人感到絕望 ... 由於我自幼就沒有接受極為嚴格的debug訓練, 因此差點就被擊倒 ... 所以要來紀錄這次的血淚歷史 XD
一開始是送測期間, 發現跑了一個晚上的 autopan, ptz就不動了, 也收不到圖 ...
先簡化環境, 於是我將機器和 camera 對接, 跑了一個晚上, 發現有機器重開、module reload、或ptz不會動的現象.
而在這些現象之前, 會有 CPU 100% 情況.
由於現象太過分散, 所以要一個個切開來看.
首先要釐清是系統還是module問題, 於是測試module什麼事都不做 ...
...... 沒事 ...
隨後測試拿掉 ONVIF, 也沒事.
這段時間, 做了一些沒意義又有點重複的實驗,
導致時間浪費不少, 這是我還要學習進步的地方.
總之, 最後把焦點鎖定在 onvif 內部的 soap api.
在多次實驗的過程中,
漸漸歸納出會造成 cpu loading 100% 的 prerequisite.
就是 memory leak !!!
於是, 接下來實驗的時間就能縮短,
只要有 memory leak 就代表問題還在,
不會像一開始那幾天, 總是要擺到系統出問題才能確認,
而這往往就耗掉了一整天的時間 ...
由於 debug 花的時間太長, 終於引起上層關切 XD
我主管也跳進來幫我指點方向,
一個關鍵字 - Valgrind, 開啟了一扇窗 !!!
為了簡化環境, 我寫了一個小執行檔,
只做 load module 跟 invoke function.
此外, 也給 module 新增了 interface function.
再搭配 gdb 檢查實驗過程中不時發生的 segmentation fault
當環境終於能正常進行模擬,
最後就是 Valgrind 的使用了 !
Valgrind 追執行檔的 memory usage, 直接下 command 即可.
但我這次是要追進 shared object 裡頭,
執行檔內就不能下 dlclose, 否則 Valgrind 會無法判斷裡面的 function ...
當 shared object 內的 function 清楚的印出來,
正好印證了我之前的猜測 - 問題出在 ONVIF/SOAP 內部.
gsoap build 出來的 soap api 或 wsse 相關函式,
裡面都會有 memory allocation.
若是用 C++ 還可以藉由 destructor 去 release 這些 memory,
但 C 就不行了,
解法就在每一個 soap api 之後,
再去呼叫 soap_destroy、soap_end、soap_done.
Valgrind 顯示, 當我使用了這三個 function 以後,
所有 malloc/calloc 都會對應到 free,
完成 !!!
雖然已經修到讓 Valgrind 秀不出 memory 存取問題,
但當我把 code 放在 embeded 上面跑,
寫一個定時印出 memory usage 的 shell script 來看,
還是有輕微的 memory leak 問題,
不過這應該跟我無關了 ....... 吧 XD
Reference:
dynamically load shared object & command line
http://tldp.org/HOWTO/Program-Library-HOWTO/dl-libraries.html#DL-LIBRARY-EXAMPLE
使用 Valgrind
http://www.cprogramming.com/debugging/valgrind.html
Valgrind 與 memory leak 有關的敘述:
http://valgrind.org/docs/manual/faq.html#faq.deflost
程式結束以前, 拿掉 dlclose, 否則 Valgrind 追不進 shared object 的 function
http://valgrind.org/docs/manual/faq.html#faq.unhelpful
留言列表