# `MishkaCmsCore.Isolated`
[🔗](https://github.com/mishka-group/mishka_cms_core/blob/v0.0.1/lib/mishka_cms_core/isolated.ex#L5)

Runs one function in a separate operating-system process: a peer BEAM started for the call
(`:peer`, in OTP's `stdlib`) and stopped after it.

For work done by native code that could take the server down with it: a NIF that crashes on a
malformed file ends the whole BEAM, and no supervisor can catch that. Run through `run/4`, the
crash ends the peer, and the caller gets `{:error, reason}` back. Every site keeps serving.

    {:ok, png} = Isolated.run(MyApp.Thumbnail, :draw, [path])
    {:error, _reason} = Isolated.run(:erlang, :halt, [139])

## What the peer has

The caller's code path (`:code.get_path/0`), so every module of the release or the project is
there to call; no application is started, and no configuration is loaded. `function` starts
what it needs.

It is the same Erlang the caller runs: the `erl` of its own ERTS, booted with the `start_clean`
boot file beside the caller's own — in a release `releases/<version>/start_clean`, with its
`RELEASE_LIB` — so it starts the same in development and in a release, with nothing on `PATH`.

## Options

  * `:timeout` — milliseconds to wait for the answer, default `30_000`; past it the peer is
    killed and the answer is `{:error, :timeout}`
  * `:env` — `[{name, value}]` of charlists for the peer's environment; `false` as the value
    removes a variable the caller has
  * `:nice` — `0..19`, the peer's scheduling priority below the caller's, given to it by the
    system's `nice` (`/usr/bin/nice` or `/bin/nice`); default `0`. Where neither is there, the
    peer runs at the caller's priority

## Answers

`{:ok, result}` with what `function` returned, else `{:error, reason}`: it raised, it exited, the
peer died, or it took too long. The caller is never linked to the peer, so nothing it does can
end the caller.

# `option`

```elixir
@type option() ::
  {:timeout, timeout()}
  | {:env, [{charlist(), charlist() | false}]}
  | {:nice, 0..19}
```

# `run`

```elixir
@spec run(module(), atom(), list(), [option()]) :: {:ok, term()} | {:error, term()}
```

---

*Consult [api-reference.md](api-reference.md) for complete listing*
