[英]Signal handling in debug and in free execution
我必須在使用 Boost.Asio 的程序中處理SIGINT
和SIGTERM
。 我boost::asio::signal_set::async_wait()
使用boost::asio::signal_set::async_wait()
。
問題是信號處理程序只有在我簡單地運行應用程序時才獲得控制權,但在調試時卻沒有。
這是一些代碼:
Proxy::Proxy():
signals_(ioContext_, SIGINT, SIGTERM)
{
signals_.async_wait(
[this](const boost::system::error_code& error, int)
{
if (!error)
ioContext_.stop();
}
);
}
Proxy::run()
{
ioContext_.run();
}
當我們run()
Proxy
, ioContext_
開始處理事件。 如果我們只是簡單地運行程序並在終端中執行Ctrl+C
,信號處理程序(即 lambda)將停止ioContext_
(正如我們所期望的)並且io_context::run
將控制權交還。 但是在調試模式下,程序對Ctrl+C
做出反應,但執行在epoll_wait()
某處停止。 如果我們繼續執行,它會掛在epoll_wait()
某個地方,依此類推。
這是執行停止位置的堆棧跟蹤:
epoll_wait
boost::asio::detail::epoll_reactor::run
boost::asio::detail::scheduler::do_one_run
boost::asio::detail::scheduler::run
boost::asio::io_context::run
Proxy::run
main
為什么它會在調試模式下發生,但在其他情況下不會發生?
這里的問題是 GDB 使用SIGINT
作為中斷程序並允許您開始調試的機制。
(gdb) info signals SIGINT
Signal Stop Print Pass to program Description
SIGINT Yes Yes No Interrupt
這就是說 GDB 不應將SIGINT
傳遞給程序,而應使用它來停止程序並將您放入 GDB 提示符。 將其發送到您的程序的最簡單機制是此時從 GDB 發送信號:
(gdb) signal SIGINT
現在您的程序應該按預期繼續運行。
根據您執行此操作的頻率,鍵入signal SIGINT
可能會變得不方便。 幸運的是,GDB 允許您修改它處理信號的方式。 您希望SIGINT
不停止程序(讓您進入 GDB 提示符)並將其傳遞給程序。
(gdb) handle SIGINT nostop 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
我們現在處於“有點不明智”的境地,因為我們不能再使用 Ctrl+C 跳轉到我們的 GDB 提示符。 您將不得不依賴預設斷點和其他機制。
如果你想更高級,你可以使用catch
和commands
來確定SIGINT
的來源(從調試使用 SIGINT 和 gdb 的程序中提升):
catch signal SIGINT
commands
if $_siginfo._sifields._kill.si_pid == 0
print "Received SIGINT from tty"
else
printf "Received SIGINT from %d; continuing\n", $_siginfo._sifields._kill.si_pid
signal SIGINT
end
end
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.