首页 > 解决方案 > 在收到 SIGSEGV 或 SIGBUS 后,进程能否以某种方式继续而不会崩溃?

问题描述

我正在处理一个项目,该项目处理影响相同数据的多个进程和线程。我有一行代码可能导致分段错误,因为可以从任何地方更新数据。对于那条特定的行,如果它导致分段错误,我想以某种方式处理它而不是让程序崩溃。如果前一个导致分段错误,我可以简单地更新内存位置。有没有办法做到这一点?

更新(我的案例的简短摘要):

我想要非常快速地访问文件。为此,我调用 mmap(2) 将该文件映射到所有访问它的进程中。我写入文件的数据采用特定数据结构的形式,并且会消耗大量内存。因此,如果出现我映射的大小不够的情况,我需要增加文件大小并使用新大小再次 mmap(2) 该文件。为了增加大小,我调用了 ftruncate(2)。ftruncate(2) 可能会被任何进程调用,因此它最终可能会缩小文件。所以我需要检查我正在访问的内存是否不会导致段错误。我正在使用 macOS。

标签: csegmentation-faultsignals

解决方案


可以工作,但是通过将信号处理程序带入图片中,您会使进程间和线程间锁定问题变得更加复杂。我想建议一种替代方法:在映射文件的第一页中保留一个字段以指示数据结构的预期大小。使用fcntl文件锁来调解对此字段的访问。

当任何进程想要更新大小时,它会拿一个写锁,读取当前值,增加它,msyncs页面(使用MS_ASYNC|MS_INVALIDATE应该足够了),然后使用ftruncate放大文件,然后放大它的文件映射,并且只有然后释放写锁。如果在获取写锁之后,您发现文件已经比您想要的大小大,只需放大映射并删除锁,不要调用 ftruncate 或更改字段。

这确保了协作进程永远不会使文件变小,并且每个进程映射的内存区域始终由分配的存储支持,因此您永远不应该得到任何SIGBUSes. 请注意,磁盘上文件的大小只会在您实际写入新分配的空间时增加,这要归功于稀疏文件的魔力。


推荐阅读