3

我在 Windows 上有一个 Perl 程序,需要在退出时执行清理操作。我使用 编写了一个信号处理程序sigtrap,但它并不总是有效。我可以拦截 Ctrl-C,但如果重新启动机器或以其他方式终止程序,则信号处理程序和 END 块都不会运行。我读过 Windows 并没有真正的信号,并且 Windows 上的信号处理有点像 Perl 中的 hack。我的问题是,如何以 Windows 方式处理异常终止?无论程序如何或为何终止(不包括无法捕获的事件),我都想运行我的清理代码。我读过 Windows 使用事件而不是信号,但我找不到有关如何在 Perl 中处理 Windows 事件的信息。

不幸的是,我没有权限从 CPAN 安装模块,所以我必须使用 vanilla ActiveState Perl。更有趣的是,我使用的大多数机器都只有 Perl 5.6.1。

编辑: 我会很感激任何答案,即使他们需要 CPAN 模块或更新版本的 Perl。我想了解 Perl 中的 Windows 事件处理,欢迎提供任何信息。

4

1 回答 1

3

在所有操作系统中,您总是可以突然终止任何程序。想想kill -9Unix/Linux 中的命令。您在任何程序上都这样做,它会立即停止。没有办法困住它。程序无法请求更多的操作系统周期进行清理。

我不了解 Unix 和 Windows 信号之间的区别,但您可以想象为什么每个操作系统都必须允许我们在 Unix 中调用的SIGKILL - 一种确定并立即杀死任何程序的方法。

想象一下,你有一个错误的程序,它拦截了一个终止请求(Unix 中的 SIGTERM),然后它进入了清理阶段。程序没有进行清理,而是陷入了一个请求越来越多内存的循环中。如果您无法拉动SIGKILL应急电源线,您就会被卡住。

最终的SIGKILL,当然是墙上的插件。拉动它,程序(以及其他所有内容)突然停止。你的程序不可能说“嗯……电源坏了,机器停止运行……最好启动旧的清理程序!

因此,您无法捕获每个程序终止信号,并且您的程序必须考虑到这一点。您可以做的是查看您的程序是否需要在运行前进行清理。在 Windows 上,您可以在程序启动时在注册表中添加一个条目,并在程序关闭并进行清理时将其删除。在 Unix 中,您可以在目录中放置一个以句点开头的文件或目录名称$ENV{HOME}

早在 1980 年代,我就为一个非常专有的操作系​​统编写了会计软件。当用户按下 ESCAPE 按钮时,我们假设立即返回到主菜单。如果用户正在输入订单,并从库存中取出物品,则交易将不完整,即使订单不完整,库存也会将商品显示为已售出。解决方案是在下次有人输入订单时检查这些不完整的订单,并在输入新订单之前取消库存更改。您的程序可能必须执行类似的操作。

于 2011-12-05T19:58:24.760 回答