乙個dba同事昨天在執行乙個命令列工具的時候發現程式hang住,問題挺有意思,值得記錄下。
首先用pstack看了下程式的呼叫棧,這是個多執行緒程式,pstack結果看到幾乎所有的執行緒都等在write呼叫上。如下是pt-pmp的輸出結果:
tue may 2718:30:06 cst 2014
55__lll_lock_wait_private,_l_lock_51,fwrite,loadconsumer::run,cthread::hook,start_thread,clone
1 write,_io_new_file_write,_io_new_file_xsputn,buffered_vfprintf,vfprintf,fprintf,loadmanager::dump,loadproducer::load_file,loadproducer::run,cthread::hook,start_thread,clone
直覺上覺得是磁碟空間滿了,讓他看了下,磁碟空間還很富裕,touch建立檔案也沒任何問題,當時此機器上還在跑乙個備份程式,io壓力不小,不過和問題本身應該關係不大。google了下__lll_lock_wait_private這個錯誤,也沒任何有用的資訊。這個工具程式本身會向乙個命令列指定的日誌檔案輸出很多程式執行結果,同時會向stderr輸出程式的執行狀態,gdb attach看了下程式具體的呼叫棧,發現程式都阻塞在fprintf(stderr)上。諮詢了下同事,他使用這個工具是通過乙個python指令碼呼叫的,呼叫的程式類似如下:
p = subprocess.popen(cmd,shell=true,stdout=subprocess.pipe,stderr=subprocess.stdout,close_fds=true)
cmd是呼叫程式的命令列,包括一系列選項。問題看起來很清晰了,通過python呼叫此命令列工具時,stdout和stderr都被重定向了subprocess.pipe,但沒有程式從此pipe讀取,那麼很快這個pipe自身的buffer都寫滿了,pstack看到的結果就是所有write都阻塞。
寫了個小程式重現了下,程式如下(隨手寫的..):
1 #include 2 #include 3 #include 4void *thr_fn(void *arg) 5
14}
1516
int main(void)
17 2324 sleep(100000);
25 }
呼叫的python指令碼如下:
1 importsubprocess
2 import
os 3 import
time
4 5 ret ={}
6 7 cmd = "
./a.out >/tmp/log
" 8
9 p = subprocess.popen(cmd,shell=true,stdout=subprocess.pipe,stderr=subprocess.stdout,close_fds=true)
10 11 ret['
status
'] =p.wait()
12 ret['
msg'] =p.stdout.readlines()
13 14 time.sleep(100000000);
執行此python指令碼,會發現很快a.out就被hang住了,表現是/tmp/log不再有新的輸出,程式呼叫棧如下:
49__lll_lock_wait_private,_l_lock_12956,buffered_vfprintf,vfprintf,fprintf,thr_fn,start_thread,clone
1write,_io_new_file_write,_io_new_file_xsputn,buffered_vfprintf,vfprintf,fprintf,thr_fn,start_thread,clone
1 nanosleep,sleep,main
解決此問題,1)maybe subprocess.popen這個程式引數可以改改?2)或者在cmd裡邊將stdout/stderr都重定向掉;3)寫命令列程式的時候要注意,呼叫的指令碼各種寫法都可能有,因此寫日誌盡量還是要規範,不要向stdout/stderr輸出過多的東西。
組裡開發的同事補充了下mysql遇到__lll_lock_wait_private 錯誤的常見場景:
"這個函式呼叫在mysql上最典型的場景就是開啟cgroup時會經常碰到這個,例如memcpy, mem alloc, free , mutext lock/unlock...."
記錄乙個statck overflow
工作中遇到一次這樣的問題 棧上的空間不夠用了,導致stack overflow,程式crash,並且coredump被寫亂了。這裡用小例子,記錄這樣的問題。include include include include define stack buffer size 10240 void thre...
記錄乙個BUG
vm版本 kali版本 centos 8 版本 vmtool版本 新裝的centos8 因為無法拖拽檔案到虛擬機器中,就重新裝了一下vmtool,安裝之後還是不行,開啟kali發現原本裝好的vmtool,現在也不能拖拽檔案了,就又在kali重灌了一次,還是不能拖拽,上網查了一下,在執行.vmware...
記錄乙個高階BUG
偶然出現一次,差點額忘記,但是一旦出現,後患無窮,記錄一下。因為新程式會在任務中一直鳴叫,但是mqtt一直沒有看到裝置入網。看log,我的裝置沒有連線到正確的平台!思考 這個bin檔案是之前上傳到平台的,其間我已經修改了工程!因為cfg檔案是不變了,裝置會讀cfg獲得平台位址!也就是我cfg改了以後...