Haskell 中的 STM 和 unsafePerformIO
STM and unsafePerformIO in Haskell
Using unsafePerformIO inside of atomically is also dangerous but for different reasons. See unsafeIOToSTM for more on this.
当涉及到使用线程和异步异常时,有一些函数可以屏蔽异步异常,以便可以安全地分配和释放资源。
但是有很多函数在幕后使用了unsafePerformIO
,例如memory
包中的allocAndFreeze,并且不难强制包含这样一个表达式的thunk在 STM 交易中。这些函数在 STM 交易中使用真的安全吗?是否存在可能导致内存泄漏或数据损坏的情况?对于这种情况,是否有等同于 mask
的东西?
谢谢
如果 IO 被 STM retry
.这有两个原因:首先,STM 重试没有 运行 异常处理程序,因此如果不安全的 IO 依赖异常处理程序释放资源(例如使用 bracket
),它们将不会被清理;其次,IO 可能会在任何时候被中断或执行多次,因此您需要确保它即使被中断也能保持程序不变性。
所以例如 allocAndFreeze
不会泄漏,因为它在内部使用 ForeignPtr
,在 GHC 中它只是固定在托管堆中的内存,所以它不依赖于异常处理程序或终结器回收内存。但是,它 可能 导致数据损坏,如果不安全的 IO 暂时破坏数据结构中的不变量,例如“分配的数组必须始终排序”,那么这种破坏可能会变得可见如果计算在那一点中断。
Using unsafePerformIO inside of atomically is also dangerous but for different reasons. See unsafeIOToSTM for more on this.
当涉及到使用线程和异步异常时,有一些函数可以屏蔽异步异常,以便可以安全地分配和释放资源。
但是有很多函数在幕后使用了unsafePerformIO
,例如memory
包中的allocAndFreeze,并且不难强制包含这样一个表达式的thunk在 STM 交易中。这些函数在 STM 交易中使用真的安全吗?是否存在可能导致内存泄漏或数据损坏的情况?对于这种情况,是否有等同于 mask
的东西?
谢谢
如果 IO 被 STM retry
.这有两个原因:首先,STM 重试没有 运行 异常处理程序,因此如果不安全的 IO 依赖异常处理程序释放资源(例如使用 bracket
),它们将不会被清理;其次,IO 可能会在任何时候被中断或执行多次,因此您需要确保它即使被中断也能保持程序不变性。
所以例如 allocAndFreeze
不会泄漏,因为它在内部使用 ForeignPtr
,在 GHC 中它只是固定在托管堆中的内存,所以它不依赖于异常处理程序或终结器回收内存。但是,它 可能 导致数据损坏,如果不安全的 IO 暂时破坏数据结构中的不变量,例如“分配的数组必须始终排序”,那么这种破坏可能会变得可见如果计算在那一点中断。