检测程序终止(C、Windows)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1394250/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 13:06:18  来源:igfitidea点击:

detect program termination (C, Windows)

cwindowsprocesstermination

提问by wonderer

I have a program that has to perform certain tasks before it finishes. The problem is that sometimes the program crashes with an exception (like database cannot be reached, etc). Now, is there any way to detect an abnormal termination and execute some code before it dies?

我有一个程序必须在完成之前执行某些任务。问题是有时程序会因异常而崩溃(例如无法访问数据库等)。现在,有没有办法检测异常终止并在它死之前执行一些代码?

Thanks.

谢谢。

code is appreciated.

代码表示赞赏。

采纳答案by cigarman

1. Win32

1.Win32

The Win32 API contains a way to do this via the SetUnhandledExceptionFilterfunction, as follows:

Win32 API 包含一种通过SetUnhandledExceptionFilter函数执行此操作的方法,如下所示:

LONG myFunc(LPEXCEPTION_POINTERS p)
{
     printf("Exception!!!\n");     
     return EXCEPTION_EXECUTE_HANDLER;
}

int main()
{
     SetUnhandledExceptionFilter((LPTOP_LEVEL_EXCEPTION_FILTER)&myFunc);    
     // generate an exception !
     int x = 0;
     int y = 1/x;
     return 0;
}

2. POSIX/Linux

2.POSIX/Linux

I usually do this via the signal()function and then handle the SIGSEGV signal appropriately. You can also handle the SIGTERM signal and SIGINT, but not SIGKILL (by design). You can use strace()to get a backtrace to see what caused the signal.

我通常通过signal()函数执行此操作,然后适当地处理 SIGSEGV 信号。您还可以处理 SIGTERM 信号和 SIGINT,但不能处理 SIGKILL(按设计)。您可以使用strace()获取回溯以查看导致信号的原因。

回答by b w

There are sysinternals forum threadsabout protecting against end-process attempts by hooking NT Internals, but what you really want is either a watchdog or peer process (reasonable approach) or some method of intercepting catastrophic events (pretty dicey).

有一些sysinternals 论坛主题是关于通过挂钩 NT Internals 来防止终端进程尝试的,但您真正想要的是看门狗或对等进程(合理的方法)或某种拦截灾难性事件的方法(非常冒险)。

Edit: There are reasons why they make this difficult, but it's possible to intercept or block attempts to kill your process. I know you're just trying to clean up before exiting, but as soon as someone releases a process that can't be immediately killed, someone will ask for a method to kill it immediately, and so on. Anyhow, to go down this road, see above linked thread and search some keywords you find in there for more. hook OR filter NtTerminateProcessetc. We're talking about kernel code, device drivers, anti-virus, security, malware, rootkit stuff here. Some books to help in this area are Windows NT/2000 Native API, Undocumented Windows 2000 Secrets: A Programmer's Cookbook, Rootkits: Subverting the Windows Kernel, and, of course, Windows? Internals: Fifth Edition. This stuff is not too tough to code, but pretty touchy to get just right, and you may be introducing unexpected side-effects.

编辑:它们使这变得困难是有原因的,但有可能拦截或阻止试图终止您的进程。我知道你只是想在退出前清理一下,但是一旦有人释放了一个不能立即杀死的进程,就会有人要求立即杀死它的方法,等等。无论如何,要沿着这条路走下去,请参阅上面的链接主题并搜索您在其中找到的一些关键字以获取更多信息。钩子或过滤器 NtTerminateProcess等。我们在这里谈论内核代码、设备驱动程序、防病毒、安全、恶意软件、rootkit 东西。在这方面提供帮助的一些书籍是Windows NT/2000 Native API未记录的 Windows 2000 秘密:程序员食谱Rootkits:颠覆 Windows 内核,当然还有Windows?内部结构:第五版。这些东西编写起来并不难,但要做到恰到好处,你可能会引入意想不到的副作用。

Perhaps Application Recovery and Restart Functionscould be of use? Supported by Vista and Server 2008 and above.

也许应用程序恢复和重启功能可能有用?受 Vista 和 Server 2008 及更高版本支持。

ApplicationRecoveryCallback Callback FunctionApplication-defined callback function used to save data and application state information in the event the application encounters an unhandled exception or becomes unresponsive.

ApplicationRecoveryCallback 回调函数应用程序定义的回调函数,用于在应用程序遇到未处理的异常或变得无响应时保存数据和应用程序状态信息。

On using SetUnhandledExceptionFilter, MSDN Social discussionadvises that to make this work reliably, patching that method in-memory is the only way to be sure your filter gets called. Advises to instead wrap with __try/__except. Regardless, there is some sample code and discussion of filtering calls to SetUnhandledExceptionFilter in the article "SetUnhandledExceptionFilter" and VC8.

在使用SetUnhandledExceptionFilter 时MSDN Social 讨论建议为了使这项工作可靠,在内存中修补该方法是确保您的过滤器被调用的唯一方法。建议改用 __try/__except 包装。无论如何,在文章“SetUnhandledExceptionFilter”和 VC8 中有一些示例代码和对过滤调用 SetUnhandledExceptionFilter 的讨论。

Also, see Windows SEH Revisitedat The Awesome Factor for some sample code of AddVectoredExceptionHandler.

此外,有关AddVectoredExceptionHandler 的一些示例代码,请参阅The Awesome Factor重新访问Windows SEH

回答by qrdl

It depends what do you do with your "exceptions". If you handle them properly and exit from program, you can register you function to be called on exit, using atexit().

这取决于你如何处理你的“例​​外”。如果您正确处理它们并从程序中退出,您可以注册要在退出时调用的函数,使用atexit().

It won't work in case of real abnormal termination, like segfault.

在真正的异常终止的情况下它不会工作,比如段错误。

Don't know about Windows, but on POSIX-compliant OS you can install signal handler that will catch different signals and do something about it. Of course you cannot catch SIGKILLand SIGSTOP.

不了解 Windows,但在兼容 POSIX 的操作系统上,您可以安装信号处理程序来捕获不同的信号并对其进行处理。当然你不能赶上SIGKILLSIGSTOP

Signal API is part of ANSI C since C89 so probably Windows supports it. See signal()syscall for details.

自 C89 以来,信号 API 是 ANSI C 的一部分,因此 Windows 可能支持它。有关signal()详细信息,请参阅系统调用。

回答by Cat Plus Plus

If it's Windows-only, then you can use SEH (SetUnhandledExceptionFilter), or VEH (AddVectoredExceptionHandler, but it's only for XP/2003 and up)

如果它仅适用于 Windows,那么您可以使用 SEH ( SetUnhandledExceptionFilter) 或 VEH ( AddVectoredExceptionHandler,但它仅适用于 XP/2003 及更高版本)

回答by DanM

Sorry, not a windows programmer. But maybe

抱歉,不是 Windows 程序员。但也许

_onexit()

Registers a function to be called when program terminates.

注册要在程序终止时调用的函数。

http://msdn.microsoft.com/en-us/library/aa298513%28VS.60%29.aspx

http://msdn.microsoft.com/en-us/library/aa298513%28VS.60%29.aspx

回答by Brooks Moses

First, though this is fairly obvious: You can never have a completely robust solution -- someone can always just hit the power cable to terminate your process. So you need a compromise, and you need to carefully lay out the details of that compromise.

首先,尽管这是相当明显的:您永远不可能有一个完全强大的解决方案——总有人可以直接敲击电源线来终止您的过程。所以你需要妥协,你需要仔细地列出妥协的细节。

One of the more robust solutions is putting the relevant code in a wrapper program. The wrapper program invokes your "real" program, waits for its process to terminate, and then -- unless your "real" program specifically signals that it has completed normally -- runs the cleanup code. This is fairly common for things like test harnesses, where the test program is likely to crash or abort or otherwise die in unexpected ways.

更强大的解决方案之一是将相关代码放入包装程序中。包装程序调用您的“真实”程序,等待其进程终止,然后——除非您的“真实”程序明确表示它已正常完成——运行清理代码。这对于测试工具之类的东西来说是相当普遍的,其中测试程序可能会崩溃或中止或以其他方式以意想不到的方式死亡。

That still gives you the difficulty of what happens if someone does a TerminateProcess on your wrapper function, if that's something you need to worry about. If necessary, you could get around that by setting it up as a service in Windows and using the operating system's features to restart it if it dies. (This just changes things a little; someone could still just stop the service.) At this point, you probably are at a point where you need to signal successful completion by something persistent like creating a file.

如果有人对您的包装器函数执行 TerminateProcess 操作,那么您仍然会遇到困难,如果这是您需要担心的事情。如有必要,您可以通过将其设置为 Windows 中的服务并使用操作系统的功能在它死机时重新启动它来解决这个问题。(这只是稍微改变了一些事情;有人仍然可以停止服务。)此时,您可能需要通过诸如创建文件之类的持久性操作来表示成功完成。

回答by RED SOFT ADAIR

I published an article at ddj.com about "post mortem debugging" some years ago.

几年前,我在 ddj.com 上发表了一篇关于“事后调试”的文章。

It includes sources for windows and unix/linux to detect abnormal termination. By my experience though, a windows handler installed using SetUnhandledExceptionFilter is not alwayscalled. In many cases it is called, but I receive quite a few log files from customers that do not include a report from the installed handlers, where i.e. an ACCESS VIOLATION was the cause.

它包括用于检测异常终止的 windows 和 unix/linux 源。但根据我的经验,使用 SetUnhandledExceptionFilter 安装的 Windows 处理程序并不总是被调用。在许多情况下,它被调用,但我从客户那里收到不少日志文件,其中不包括来自已安装处理程序的报告,即访问冲突是原因。

http://www.ddj.com/development-tools/185300443

http://www.ddj.com/development-tools/185300443