【问题标题】:How to properly handle SIGBREAK when closing console?关闭控制台时如何正确处理 SIGBREAK?
【发布时间】:2014-08-12 13:52:25
【问题描述】:

我必须捕捉 单击控制台的关闭按钮 事件,它对应于 ctrl-break 事件 SIGBREAK 但显然有一种超时,它不允许我再做任何事情超过 5 秒,在什么程序似乎被中止之后(所以消息 “正确结束!” 永远不会发生)。

如何强制系统执行关闭操作直到结束(或将超时时间延长至 60 秒)?

注意:用同样的方法,我可以在doStuffs();之前使用fflush(stdout);成功处理CTRL+C事件(SIGINT

注意 2:我的代码基于这个答案:https://stackoverflow.com/a/181594/1529139

#include <csignal>

void foo(int sig)
{
    signal(sig, foo); // (reset for next signal)

    // do stuffs which takes aboutly 15 seconds
    doStuffs();

    cout << "Properly ended !";
}

int main(DWORD argc, LPWSTR *argv)
{
    signal(SIGBREAK, foo);
    myProgramLoop();
}

【问题讨论】:

    标签: c++ windows process signals


    【解决方案1】:

    我相信超时是固定的,没有办法修改它,见API reference

    如果进程在某个超时期限内(CTRL_CLOSE_EVENT 为 5 秒,CTRL_LOGOFF_EVENT 和 CTRL_SHUTDOWN_EVENT 为 20 秒)没有响应,系统也会显示该对话框。

    进程可以使用 SetProcessShutdownParameters 函数来阻止显示 CTRL_LOGOFF_EVENT 和 CTRL_SHUTDOWN_EVENT 对话框。在这种情况下,系统只会在 HandlerRoutine 返回 TRUE 或超时时间过后终止进程。

    另一种方法怎么样,只需禁用控制台窗口的关闭按钮:

    GUITHREADINFO info = {0};
    info.cbSize=sizeof(info);
    GetGUIThreadInfo(NULL, &info);
    HMENU hSysMenu = GetSystemMenu(info.hwndActive, FALSE);
    EnableMenuItem(hSysMenu, SC_CLOSE, MF_GRAYED);
    

    现在您可以安全地通过 Ctrl-C 或其他键盘输入来处理关闭操作。

    【讨论】:

    • 这是否意味着不可能以安全的方式关闭控制台? (使用关闭按钮或如果被另一个进程终止)
    • 您可以安全地关闭,但您必须在 5 秒的宽限期内完成。无法将其扩展为 Microsoft wants to avoid the arms race
    猜你喜欢
    • 2012-01-26
    • 2016-03-24
    • 2011-12-20
    • 2015-05-27
    • 2014-07-19
    • 1970-01-01
    • 2015-11-29
    • 2012-08-20
    • 2016-11-30
    相关资源
    最近更新 更多