Perl 在可存储写入期间是不是安全地延迟 INT 信号?

Posted

技术标签:

【中文标题】Perl 在可存储写入期间是不是安全地延迟 INT 信号?【英文标题】:Does Perl safely defer INT signals during a Storable write?Perl 在可存储写入期间是否安全地延迟 INT 信号? 【发布时间】:2013-02-20 02:02:13 【问题描述】:

我担心在执行Storable::store 操作时数据损坏。我正在向 NFS 写入大约 100 MB 的数据,以在特定检查点备份我的计算,但这个过程并不十分迅速。

为了防止损坏,我有一个SIGINT 信号处理程序。在调用Storable::store 之前,设置了一个全局变量,表明终止它是不安全的。 Storable::store 完成后,该全局变量将立即返回一个值以指示可以中断。

该全局变量用于指示信号处理程序是否会调用die,或者它是否只会打印一条“尚不能停止”的语句。

但我真的有帮助吗?我现在从阅读perlipc 中看到,中断 IO 有时是安全完成的,有时不是......也就是说,如果我的信号处理程序最终在我的 Storeable::store 操作中间被调用,那么短暂的转移到我的信号处理程序子程序可能仍然足以把事情搞砸。

有谁知道Storable 在这种情况下的表现如何?或者我的信号处理设置真的合适吗?

【问题讨论】:

有other things to be concerned about with Storable。 真正的快...布赖恩...大粉丝!我有“学习 Perl”和“中级 Perl”。我喜欢这两本书。他们让我对编程的热情超过了其他任何东西。感谢您提供如此精彩的教学著作。 【参考方案1】:

从 5.8.1 开始,Perl 使用“safe signals”(默认情况下)。当您通过%SIG 设置信号处理程序时,Perl 实际上安装了一个简单的信号处理程序,它除了增加一个计数器之外什么都不做。在 Perl 操作之间,Perl 检查计数器是否非零,如果是,则调用您的信号处理程序。这样,您的信号处理程序就不会在系统调用或库调用中间执行。

您只需要担心两件事:

在信号处理程序中修改全局变量(例如 $!)。 系统调用返回 EINTR 或 EAGAIN,因为在调用期间有信号进入。

【讨论】:

对代码的检查表明 Storable.xs 似乎只使用了 PerlIO_write;不知道会自动重新启动调用(假设它最终执行系统调用并且没有被 IO 层转移到 perl 代码) @ysth,我对此表示怀疑。 Storable 在从 PerlIO_write 收到错误时会做什么?【参考方案2】:

如果您真的担心SIGINT 可能会破坏store,请尝试将SA_RESTART 添加到您的信号处理程序中。在 Linux 上,这将强制系统调用在收到信号时自动重试。这可能会无限期地推迟您的信号处理程序,因为SIGINT 将无法中断 I/O 操作。但是,它应该能够在任何中断情况下安全运行Storable::store

【讨论】:

以上是关于Perl 在可存储写入期间是不是安全地延迟 INT 信号?的主要内容,如果未能解决你的问题,请参考以下文章

perl 中的无缓冲 IO

如何在可迭代的 Spring Boot Flux 中延迟发射每个项目

Perl:写入速度之谜?

Java 中的 volatile int 是线程安全的吗?

使用多线程在 GNU C 中使用写入函数是不是安全

如何安全地从多个线程并行访问和写入复杂容器?