[轉] gdb中忽略訊號處理

來源:互聯網
上載者:User

標籤:

訊號(Signals)

訊號是一種非強制中斷,是一種處理非同步事件的方法。一般來說,作業系統都支援許多訊號。尤其是UNIX,比較重要應用程式一般都會處理訊號。UNIX定義了許 多訊號,比如SIGINT表示中斷字元訊號,也就是Ctrl+C的訊號,SIGBUS表示硬體故障的訊號;SIGCHLD表示子進程狀態改變訊號; SIGKILL表示終止程式啟動並執行訊號,等等。訊號量編程是UNIX下非常重要的一種技術。

GDB有能力在你偵錯工具的時候處理任何一種訊號,你可以告訴GDB需要處理哪一種訊號。你可以要求GDB收到你所指定的訊號時,馬上停住正在啟動並執行程式,以供你進行調試。你可以用GDB的handle命令來完成這一功能。

handle
在GDB中定義一個訊號處理。訊號可以以SIG開頭或不以 SIG開頭,可以用定義一個要處理訊號的範圍(如:SIGIO-SIGKILL,表示處理從SIGIO訊號到SIGKILL的訊號,其中包括SIGIO, SIGIOT,SIGKILL三個訊號),也可以使用關鍵字all來標明要處理所有的訊號。一旦被調試的程式接收到訊號,運行程式馬上會被GDB停住,以 供調試。其可以是以下幾種關鍵字的一個或多個。

nostop
當被調試的程式收到訊號時,GDB不會停住程式的運行,但會打出訊息告訴你收到這種訊號。
stop
當被調試的程式收到訊號時,GDB會停住你的程式。
print
當被調試的程式收到訊號時,GDB會顯示出一條資訊。
noprint
當被調試的程式收到訊號時,GDB不會告訴你收到訊號的資訊。
pass
noignore
當被調試的程式收到訊號時,GDB不處理訊號。這表示,GDB會把這個訊號交給被偵錯工具會處理。
nopass
ignore
當被調試的程式收到訊號時,GDB不會讓被偵錯工具來處理這個訊號。


info signals
info handle
查看有哪些訊號在被GDB檢測中。


另外補充:

訊號的處理
程式是和網路相關的,調試期間經常地收到SIGPIPE,導致gdb停下來。看了一下gdb info,解決方案很簡單。用handle命令設定一下預設signal的處理行為就可以了:
   handle SIGPIPE nostop
如果連提示資訊都不想看見,就可以這樣設定:
   handle SIGPIPE nostop noprint
就可以了。其他相關訊號也可以類似處理。想瞭解目前的signal狀態可以使用info signal察看。

啟動設定檔
GDB使用中比較麻煩的事情,就是每次啟動,還要手動敲一把命令,特別是斷點比較多的情況,這個特便影響,工作效率。查了一下gdb info,gdb支援自動讀取一個啟動指令檔.gdbinit,所以經常輸入的啟動命令,就都可以寫在gdb啟動目錄的.gdbinit裡面。比如
.gdbinit:
   file myapp
   handle SIGPIPE nostop
   break ss.c:100
   break ss.c:200
   run
GDB和bash類似,也支援source這個命令,執行另外一個指令檔。所以可以修改一下.gdbinit:
.gdbinit:
   file myapp
   handle SIGPIPE nostop
   source gdb.break
   run
gdb.break:
   break ss.c:100
   break ss.c:200
這樣修改的斷點配置,只需要編輯gdb.break就可以了。再後來,偶而還是需要單獨啟動GDB,不想執行自動指令碼,於是又改進了一下。首先把.gdbinit命名為gdb.init,然後定義一個shell alias:
   $ alias .gdb=”gdb -x gdb.init”

這樣如果需要使用自動指令碼,就用.gdb命令,否則用gdb進入互動狀態的gdb。這樣配置以後可以一個簡單命令就開始調試,整個效率就能提高不少。

注:轉自http://blog.scaner.i.thu.cn/index.php/2006/04/15/gdb-tips-1/

註解

1alias命令

alias顧名思義就是起別名的意思,在linux裡,可以通過alias命令為常用命令設定捷徑,命令格式如下: alias name=‘command‘ 例如:alias del=‘rm‘

欲顯示系統已有別名,直接使用 alias或alias -p

若需要設定的命令別名比較多,可以直接修改/etc/bashrc或~/.bashrc,將需要的別名寫到裡面即可,不同之處是/etc/bashrc設定的別名對於所有登入使用者都起作用,而~/.bashrc只對目前使用者起作用。

 

比如:

handle SIGUSR2 nostop

 

 

一篇不錯的文章,講的是gdb中的訊號(signal)相關調試技巧

    轉自Magic C++論壇

    http://www.magicunix.com/index_ch.html

    http://www.magicunix.com/cgi-bin1/forum_cn/ultimatebb.cgi?ubb=get_topic&f=1&t=000060#000003

    引用:

    --------------------------------------------------------------------------------

    原發貼者 Couger:

    我寫了一個INT訊號的處理函數,在處理函數裡設定斷點後go,但是在console下按Ctrl-C後MC並沒有進入處理函數,而console下的程式也直接退出,沒有給出希望的輸出。

    --------------------------------------------------------------------------------

    在console下按Ctrl-C後確實發送了SIGINT訊號,但是gdb裡的預設設定將會導致由GDB截獲的該資訊,調試的應用程式無法接受到該訊號。

    有兩種方法可以使調試的應用程式接受到訊號:

    (1)改變gdb訊號處理的設定

    比如,以下設定會告訴gdb在接收到SIGINT時不要停止、列印出來、傳遞給偵錯目標程式

    =====================================

    (gdb) handle SIGINT nostop print pass

    SIGINT is used by the debugger.

    Are you sure you want to change it? (y or n) y

    Signal Stop Print Pass to program Description

    SIGINT No Yes Yes Interrupt

    (gdb)

    =====================================

    (2)使用gdb命令直接向調試的應用程式發送訊號

    首先在你希望發送訊號的語句處設定斷點,然後運行程式,當停止到斷點所在位置後,用gdb的signal命令發送訊號給偵錯目標程式

    ====================================

    (gdb) signal SIGINT

    Continuing with signal SIGINT.

    Breakpoint 1, handler (signal=2) at main.cpp:15

    15 printf("Signal handler...\n"

    

    ;

    ====================================

    ;-( 但是這兩種方法目前MC都還不支援,所以需要等新版本的MC才可以方便的支援你這種調試情況,呵呵。臨時先手工調試一下吧。

    新版本將會增加

    (1)調試器的訊號處理設定

    (2)支援發送訊號命令

    調試用例:

    ============

    /*

    * This program is uninterruptable with

    * Ctrl+C, uses signal handler

    */

    #include ;

    #include ;

    #include ;

    /* The signal handler function */

    void handler( int signal ) {

    printf("Signal handler...\n"

    

    ;

    psignal( signal, "Signal: "

    

    ;

    } /*handler*/

    main() {

    /* Registering the handler, catching

    SIGINT signals */

    signal( SIGINT, handler );

    /* Do nothing */

    while( 1 ) {

    printf("Running...\n"

    

    ;

    sleep(10);

    } /*while*/

    } /*main*/

    ============

    改變gdb的訊號處理設定

    ============

    5.3 Signals

    A signal is an asynchronous event that can happen in a program. The

    operating system defines the possible kinds of signals, and gives each

    kind a name and a number. For example, in Unix SIGINT is the signal a

    program gets when you type an interrupt character (often C-c); SIGSEGV

    is the signal a program gets from referencing a place in memory far

    away from all the areas in use; SIGALRM occurs when the alarm clock

    timer goes off (which happens only if your program has requested an

    alarm).

    Some signals, including SIGALRM, are a normal part of the functioning

    of your program. Others, such as SIGSEGV, indicate errors; these

    signals are fatal (they kill your program immediately) if the program

    has not specified in advance some other way to handle the signal.

    SIGINT does not indicate an error in your program, but it is normally

    fatal so it can carry out the purpose of the interrupt: to kill the

    program.

    GDB has the ability to detect any occurrence of a signal in your

    program. You can tell GDB in advance what to do for each kind of

    signal.

    Normally, GDB is set up to let the non-erroneous signals like SIGALRM

    be silently passed to your program (so as not to interfere with their

    role in the program‘s functioning) but to stop your program immediately

    whenever an error signal happens. You can change these settings with

    the handle command.

    info signals

    info handle

    Print a table of all the kinds of signals and how GDB has been told to

    handle each one. You can use this to see the signal numbers of all the

    defined types of signals.

    info handle is an alias for info signals.

    handle signal keywords...

    Change the way GDB handles signal signal. signal can be the number of a

    signal or its name (with or without the `SIG‘ at the beginning); a list

    of signal numbers of the form `low-high‘; or the word `all‘, meaning

    all the known signals. The keywords say what change to make.

    The keywords allowed by the handle command can be abbreviated. Their full names are:

    nostop

    GDB should not stop your program when this signal happens. It may still

    print a message telling you that the signal has come in.

    stop

    GDB should stop your program when this signal happens. This implies the print keyword as well.

    print

    GDB should print a message when this signal happens.

    noprint

    GDB should not mention the occurrence of the signal at all. This implies the nostop keyword as well.

    pass

    noignore

    GDB should allow your program to see this signal; your program can

    handle the signal, or else it may terminate if the signal is fatal and

    not handled. pass and noignore are synonyms.

    nopass

    ignore

    GDB should not allow your program to see this signal. nopass and ignore are synonyms.

    When a signal stops your program, the signal is not visible to the

    program until you continue. Your program sees the signal then, if pass

    is in effect for the signal in question at that time. In other words,

    after GDB reports a signal, you can use the handle command with pass or

    nopass to control whether your program sees that signal when you

    continue.

    The default is set to nostop, noprint, pass for non-erroneous signals

    such as SIGALRM, SIGWINCH and SIGCHLD, and to stop, print, pass for the

    erroneous signals.

    You can also use the signal command to prevent your program from seeing

    a signal, or cause it to see a signal it normally would not see, or to

    give it any signal at any time. For example, if your program stopped

    due to some sort of memory reference error, you might store correct

    values into the erroneous variables and continue, hoping to see more

    execution; but your program would probably terminate immediately as a

    result of the fatal signal once it saw the signal. To prevent this, you

    can continue with `signal 0‘. See section Giving your program a signal.

    ============

    直接使用gdb signal命令發送訊號給偵錯目標程式

    ================

    三、產生訊號

    使用singal命令,可以產生一個訊號給被調試的程式。如:中斷訊號Ctrl+C。這非常方便於程式的調試,可以在程式啟動並執行任意位置設定斷點,並在該斷點用GDB產生一個訊號,這種精確地在某處產生訊號非常有利程式的調試。

    文法是:signal ;,UNIX的系統訊號通常從1到15。所以;取值也在這個範圍。

    single命令和shell的kill命令不同,系統的kill命令發訊號給被偵錯工具時,是由GDB截獲的,而single命令所發出一訊號則是直接發給被偵錯工具的。

    ====================

[轉] gdb中忽略訊號處理

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.