2015-05-01 20 views
2

我已經做了google多次,爲信號處理程序中的backtrace()找到正確的解決方案,並嘗試幾乎所有東西,但是我無法在信號處理程序中成功獲取回溯 - 這不是SIGUSR1處理程序。如何在過程信號處理程序(armv7-uclibc)中獲得正確的回溯?

  • 啓用uClibc的配置UCLIBC_HAS_BACKTRACE = y和編譯它
  • 證實libubacktrace.so創建
  • 編譯我的應用程序二進制文件下列選項 -g -rdynamic -fexception或-funwind桌
  • 二進制本身似乎被「剝奪」

但是,我沒能得到充分的回溯來自信號處理器。 只打印了我在信號處理程序中調用的函數地址。

如果我使用target-gdb binary並使用gdb -pid命令附加進程,我可以正確地獲得完整的backtrace。

另外,我試過pstack,但(pstack-1.2 - 嘗試過arm-patch,但它很可怕......沒有打印)不是很有幫助。

有什麼建議嗎?


1)在生成文件編譯器選項

CFLAGS + = -g -fexceptions -funwind桌-Werror $(WARN)...

2)的代碼

的代碼非常簡單。

#define CALLSTACK_SIZE 10 

static void print_stack(void) { 
    int i, nptrs; 
    void *buf[CALLSTACK_SIZE + 1]; 
    char **strings; 

    nptrs = backtrace(buf, CALLSTACK_SIZE); 
    printf("%s: backtrace() returned %d addresses\n", __func__, nptrs); 

    strings = backtrace_symbols(buf, nptrs); 

    if(strings == NULL) { 
     printf("%s: no backtrace captured\n", __func__); 
     return; 
    } 

    for(i = 0; i < nptrs; i++) { 
     printf("%s\n", strings[i]); 
    } 

    free(strings); 
} 

... 
static void sigHandler(int signum) 
{ 
    printf("%s: signal %d\n", __FUNCTION__, signum); 
    switch(signum) { 
    case SIGUSR2: 
     // told to quit 
     print_stack(); 
     break; 
    default: 
     break; 
    } 
} 
+0

您需要顯示一些代碼,特別是您的信號處理程序代碼。請修改您的問題以改進它。 –

+0

你正在編寫什麼樣的應用程序?你有一些事件循環? –

+0

...這個過程正在等待來自其他進程的「消息」。 SysV IPC消息是在多個進程之間建立起來的,它們將消息彼此發佈。除此之外,沒有太多的特殊操作...沒有插座I/O。它通過調用open()和write()來更新字符設備,但只寫入1個字節。 – user2526111

回答

3

閱讀仔細signal(7)signal-safety(7)

的信號處理程序被限制到呼叫(直接或間接)僅異步信號安全函數(實際地說,最syscalls(2)只)和backtrace(3)或者甚至printf(3)malloc(3)free不是異步信號安全。所以你的代碼是不正確的:信號處理器sigHandler調用printf和間接(通過print_stackfree並且它們不是異步信號安全的。

所以你唯一的選擇是使用gdb調試器。

瞭解更多關於POSIX signal.h & signal concepts。實際上,信號處理程序可以做的幾乎唯一明智的事情是設置一些全局的,線程本地的或靜態的,這些都必須在其他地方進行測試。它也可以直接write(2)幾個字節到pipe(7),你的應用程序可以在別處讀取(例如,在它的事件循環中,如果它是一個GUI應用程序)。

您也可以使用Ian Taylor的libbacktrace from inside GCC(假設您的程序是用調試信息編譯的,例如-g)。不能保證在信號處理程序中工作(因爲它不僅僅使用異步信號安全功能),但它實際上非常有用。

請注意,內核在處理信號時正在爲sigreturn(2)設置呼叫幀(在call stack中)。

您也可以使用(特別是如果您的應用程序是單線程)sigaltstack(2)有一個替代信號堆棧。我不確定這會有幫助。

如果你有一個事件循環,你可能會考慮使用Linux專用的signalfd(2)並要求你的事件循環爲poll它。對於SIGTERMSIGQUITSIGALRM這是一個非常有用的技巧。

+0

謝謝...讓我試試吧! – user2526111

相關問題