# Overview of resource management in Haskell

October 4, 2014
Yuras Shumovich

(Originally posted here)

Writing exception safe code is hard in any language. But in Haskell it is especially hard because of asynchronous exceptions.

## Problem: How to ensure all resources will be freed?

File descriptors, tcp ports, memory etc. They are limited resources. If you are not careful enough, you’ll run out of them sooner of later. For long running applications it is mission critical to free resources as soon as possible.

## Solution 1: Manually free resources

do
resource <- allocate
use resource
free resource

Allocate resource, use it and free it. Very easy but completely wrong. First of all, it is too easy to forget to free resource. But even if you never forget anything, you are not safe enough – an exception can abort normal control flow leaving resources alive forever.

## Solution 2: finally

do
resource <- allocate
use resource
finally free resource

Much better – the resource will be freed even if use throws exception. Probably that is OK in most languages, but it is still wrong in Haskell. Asynchronous exception can be raised in small window between allocate and finally or between finally and free.

mask $\restore -> do resource <- allocate restore (use resource) finally free resource The idea is pretty clear – disable asynchronous exceptions in critical parts of code. This idiom is the most widely used. It is even implemented in standard library under bracket name. The solution is simple and robust, it works in almost all cases. But there are few cases that don’t fit the pattern well. ## Use case 1: free resource earler Sometimes you may want to free resource before bracket does that: braket allocate free$ \resource -> do
use resource
if ...
then free resource
else ...

But there is no way to let bracket know that you already freed the resource. As a result you have double free error.

## Solution 3: ResourceT

resourcet package provides monadic scope for deterministic resource allocation. All resources will be freed on exit from the scope. Sounds similar to bracket, but in addition it lets you free resource easer. Here is an example:

import qualified Control.Monad.Trans.Resource as R
R.runResourceT $do (key, resource) <- R.allocate allocate free use resource if ... then R.release key else ... Each resource is identified with unique key, that you can use to free the resource earler and be sure release action will be called exactly once. ## Use case 2: let resource escape to outer scope That’s common pattern in c++: attach heap object to auto_ptr and release it before return: std::auto_ptr<Foo> createFoo() { auto_ptr<Foo> foo(new Foo); do_something(); // potentially throws exception return foo; } Here if do_something throws an exception, auto_ptr will delete the object on exit from local scope. Otherwise Foo escapes to outer scope. Obviously it is not possible with Haskell’s bracket pattern. Probably you can do that with ResourceT, but it is not supported out of the box. ## Soulution 4: type safe monadic regions TODO: example regions package provides type safe monad scope with ability to transfer resource ownership to outler scope. In addition it uses black type level magic to ensure that you can’t return resource from the region without transfering ownership (yes, it uses the same trick as ST monad.) ## Dynamic regions There is a number of (probably rare) situations where neither solution can be easily applied. For example, you may need to transfer resource to other thread; or attach resources to an object (explicit owner); or combine a bunch of resources into one umbrella resource to hide implementation details. What you need here is dynamic regions that you can pass here and there, store in data types, etc. ## io-region The package provides dynamic regions plus ability to free resources earler and atomically transfer them between regions. It is not type safe in the same sence as region package, but is much easer to use and understand. ### Exampes import Constrol.IO.Region (region) import qualified Constrol.IO.Region as R ... region$ \r -> do
resource <- R.alloc_ r allocate free
use resource
-- resource will be automatically freed here

...
region $\r -> do (resource, key) <- R.alloc r allocate free use resource if ... then R.free key -- free it earler else use resource ... region$ \r1 -> do
resource <- region $\r2 -> do (resource1, key) <- R.alloc r2 allocate free use resource resource R.moveTo r1 -- transfer ownership to region r1 return resource doSomethingElse resource -- resource will be freed here ... region$ \r1 -> do
(r2, r2Key) <- R.alloc r1 R.open R.close  -- region is a resource too
resource <- R.alloc r2 allocate free
use resource
r2Key R.moveTo r3  -- move region r2 ownership (and also the resource) to other region