【问题标题】:How to handle abnormal program termination in Perl on Windows如何在 Windows 上处理 Perl 中的异常程序终止
【发布时间】:2012-01-13 06:03:34
【问题描述】:

我在 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 事件处理,欢迎提供任何信息。

【问题讨论】:

  • Perl 5.6.1.. 那是什么,就像 10 岁?你在这些机器上安装了 Win98/2000/ME 吗? =)
  • 我们在所有台式机上都使用 Windows XP。当微软停止支持 XP 时,我们有望在 Windows 7 上运行。不管你信不信,我们的一些机器仍然使用 IE6,因为我们的一些内部应用程序无法在其他任何东西上运行。
  • 我的意思是作为参考。perl 5.6.1 与那些操作系统一样过时。这总是让我想知道为什么人们不更新 perl。不更新任何其他软件并不是一个好主意。

标签: windows perl events signals activestate


【解决方案1】:

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

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

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

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

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

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

【讨论】:

  • 我明白,但这不是我要问的。在我最初的问题中,我说“排除无法捕获的事件”。我知道我无法捕捉到 Windows 中的 SIGKILL 或其他立即致命的错误,但我希望能够捕捉到 SIGTERM 和类似的等价物。但由于某种原因,我的信号处理程序除了在 Ctrl-C 上没有被调用。我想学习如何直接使用 Windows 事件,而不是通过不完整的 Unix 信号模拟。
  • @Jonathan - 很抱歉造成混乱。 Perl 在 Cntrl-C 上模拟 SIGTERM,但除此之外,Windows 不使用可以捕获的信号。您可以查看与 Windows 事件处理相关的 Win32::Events。这就是 Windows 使用而不是信号的方式。
  • 对 Win32::Events 的引用很有帮助,但文档仅说明了如何创建和操作事件。我需要捕获进程被终止时生成的任何事件。你能指点我这方面的任何信息吗?我用谷歌搜索了“在 perl 中捕获 windows 事件”,但几乎一无所获。
  • @Jonathan - 我不是 Windows 程序员。据我了解,很少有通用的 Win32 信号。 Win32 使用事件,由客户端和服务器创建一组用于通信的事件。有一些pre-defined system wide events,例如CTRL_C_EVENTCTRL_BREAK_EVENTCTRL_CLOSE_EVENTCTRL_LOGOFF_EVENTCTRL_SHUTDOWN_EVENT。您可以尝试使用 `Win32::Events 捕获这些。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-08-13
  • 1970-01-01
  • 2016-09-21
  • 1970-01-01
  • 2013-01-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多