當我在編譯運行 FastScripts時出現了如下問題
FastScripts [...] is calling TIS/TSM in non-main thread environment,
ERROR : This is NOT allowed. Please call TIS/TSM in main thread!!!
不知道是什么原因導致的這個問題。
有時候蘋果添加了想這樣的log信息都提供了足夠的解決信息。有的是建議我們停止使用過時的方法、或者像現在這種場景中,提供一個象征性的設置為0的斷點并且完全對應了代碼所在。例如,我打開控制臺應用程序的快速調查顯示:
default 11:54:18.482226 -0400 com.apple.WebKit.WebContent
Set a breakpoint at SLSLogBreak to catch errors/faults as they are logged.
這個特定的警告好像和我的程序并沒有什么關系,但如果是這樣的,我需要去學習更多有關TIS/TSM 相關的東西,但是我并不知道改怎么做,我甚至都不知道用了TIS/TSM ,什么是TIS/TSM ??
在蘋果平臺工作了足夠久之后我知道了TSM代表的是文本服務的工具,然而我還是不知道是否用過這個東西、或正在我的程序中使用著這個框架、這是蘋果還是我在使用的東西?
理想情況下我們可以通過設置斷點來打印相關信息,但現在的情況出乎意料的困難啊。我們有NSLog, os_log, printf, fprintf, write等方法去獲取信息。我可以通過全面的方法捕捉任何寫入控制臺的方法,但是我是否需要通過這種方法去獲取信息呢?(在這種特殊的情況下,我深入研究了CFLog)。
這是一個場景,結合lldb強大的“正則表達式斷點”和“斷點指令”可以幫助很大。早在我的應用程序的啟動,警告消息記錄,我就進入了lldb,添加斷點:
(lldb) break set -r TIS|TSM.*
我覺得無論是什么函數導致這個問題都會包含與這個前綴相關的框架,這是一個比較可行的猜測。
Breakpoint 5: 634 locations.
點擊繼續讓我的程序繼續運行,但是它有634的相關的斷點,時不時的出現。我更傾向于讓它自己處理并自行整理出細節:
(lldb) break command add 5
Enter your debugger command(s). Type 'DONE' to end.
> bt
> c
> DONE
(lldb) c
Process 16022 resuming
break command add 的功能是
Add LLDB commands to a breakpoint, to be executed whenever the breakpoint
is hit. If no breakpoint is specified, adds the commands to the last
created breakpoint.
bt 的功能是顯示當前堆棧
c 的功能是繼續執行所有進程
這一系列命令的作用是在命中斷點5的時候調用bt方法獲取調用堆棧,然后繼續運行,在程序運行之后,就可以查看最近被調用的命令了。
thread #7, stop reason = breakpoint 5.568
frame #0: 0x00007fff2cd520fd HIToolbox`TSMGetInputSourceProperty
frame #1: 0x00000001003faef2 RSFoundation`-[RSKeyboardStatus update](self=0x00006000002b8c00, _cmd="update") at RSKeyboardStatus.m:56
[...]
Command #2 'c' continued the target.
2018-08-14 12:15:40.326538-0400 FastScripts[16022:624168] pid(16022)/euid(501) is calling TIS/TSM in non-main thread environment, ERROR : This is NOT allowed. Please call TIS/TSM in main thread!!!
經過查找之后發現以上問題,很顯然,這是我的代碼,我調用TSM的方法去處理FastScripts的鍵盤的快捷鍵功能, thread #7中很顯然能夠發現這不是處于主線程中,我應該感到羞愧。。。。
但是我很自豪能夠通過lldb定位到了問題所在,下次你如果遇到無法定位問題的時候,可以嘗試通過基于正則表達式的斷點和一系列的命令來確定問題。
總結
當遇到無法定位的問題可以嘗試通過lldb和正則來定位問題。
就如原作者遇到了的問題做了如下幾點:
1.通過設置一個正則表達式的斷點來定位問題;
2.因為有太多滿足條件的情況原作者通過lldb批量處理調用堆棧內容;
3.查看日志最終定位到問題。
更多的lldb方法,在lldb中通過help命令去獲取