Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

STM and unsafePerformIO in Haskell

Tags:

haskell

stm

The documentation for STM states that:

Using unsafePerformIO inside of atomically is also dangerous but for different reasons. See unsafeIOToSTM for more on this.

When it comes to using threads and async exceptions, there are functions to mask asynchronous exceptions so that resources can be safely allocated and freed.

But there are alot of functions that use unsafePerformIO behind the scenes, for example allocAndFreeze in the memory package, and it's not hard to force a thunk containing such an expression inside an STM transaction. Are those functions actually safe to use inside an STM transaction? Are there circumstances where it could lead to memory leaks or data corruption? Is there an equivalent of mask for this circumstance?

Thanks

like image 578
Scott Avatar asked Jun 08 '20 15:06

Scott


1 Answers

Ordinarily safe uses of unsafePerformIO may lead to resource leaks (not necessarily memory specifically) or data corruption if the IO is interrupted by an STM retry. This is for two reasons: first, STM retries do not run exception handlers, so if the unsafe IO relies on exception handlers to release resources (e.g. with bracket), they will not be cleaned up; and second, the IO may be interrupted at any point or executed multiple times, so it’s up to you to ensure it maintains program invariants even if interrupted.

So for example allocAndFreeze will not leak, because it uses ForeignPtr internally, which in GHC is just pinned memory in the managed heap, so it doesn’t rely on exception handlers or finalizers to reclaim the memory. However, it may cause data corruption in the sense that, if the unsafe IO temporarily breaks invariants in a data structure such as “the allocated array must always be sorted”, that breakage may become visible if the computation is interrupted at that point.

like image 144
Jon Purdy Avatar answered Nov 20 '22 12:11

Jon Purdy