# Exception inside a spawn block \*should\* crash the program

**URL:** <https://forum.crystal-lang.org/t/exception-inside-a-spawn-block-should-crash-the-program/3853>\
**Category:** Help & Support\
**Created:** [September 16, 2021, 7:28pm UTC](https://forum.crystal-lang.org/t/exception-inside-a-spawn-block-should-crash-the-program/3853 "2021-09-16T19:28:46Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![haarts](https://avatars.discourse-cdn.com/v4/letter/h/8797f3/32.png) [@haarts](https://forum.crystal-lang.org/u/haarts)\
**Post date:** [September 16, 2021, 7:28pm UTC](https://forum.crystal-lang.org/t/exception-inside-a-spawn-block-should-crash-the-program/3853/1 "2021-09-16T19:28:47Z")

</div>

I have a very simple program. What it does is listen to a Postgres channel, when a notification arrives it does some work and then continues to listen again.

It can happen that a notification is somehow corrupted. Then the program should just crash. I have systemd setup to restart it and it is no big deal.

```auto
  spawn do
    begin
      PG.connect_listen(ENV["POSTGRES"], "new_measurements") do |n|
        server_id, file_system_id, measurement_id = n.payload.split(",")

        capacity = pg.scalar("SELECT capacity FROM measurements WHERE id = $1", measurement_id).as(Int32)
        if capacity > 90
          pp "panic!"
        end
      end
    ensure
      pg.close
    end
  end
  sleep

```

The exception is for instance thrown at the `pg.scalar` query. But I really want to catch all exceptions with an ensure and then crash/exit the program.  
When an exception occurs now the program just hangs. It enters the ensure clause and then hangs on the `sleep` call? I don’t really know.

The `spawn` and `sleep` are necessary otherwise the program will exit immediately without processing notifications.

I’m pretty new to Crystal and I’m not sure what the canonical way of handling this is.

---

<div class="post-metadata">

**Author:** ![jhass](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/jhass/32/1779_2.png) [@jhass](https://forum.crystal-lang.org/u/jhass)\
**Post date:** [September 17, 2021, 7:13am UTC](https://forum.crystal-lang.org/t/exception-inside-a-spawn-block-should-crash-the-program/3853/2 "2021-09-17T07:13:29Z")

</div>

Yes, an exception only “crashes” the current fiber/coroutine, it does not affect the main fiber that spawned it.

The extra `spawn` should not be necessary, the program exits without the `sleep` because `connect_listen` itself spawns the poll event loop in a new fiber: [crystal-pg/connection.cr at master · will/crystal-pg · GitHub](https://github.com/will/crystal-pg/blob/master/src/pg/connection.cr#L50)

Without testing it myself I suspect something like a close wait channel will work for your usecase:

```auto
notification_errors = Channel(Exception).new
pg = PG.connect(...)
PG.connect_listen(...) do |n|
  begin
    capacity = pg.scalar(...)
    raise "bad capacity" if capacity > 90
  rescue e : Exception
    notification_errors.send e
  end
end

# This blocks the main fiber until something is send to the channel
e = notification_errors.receive 

pg.close
abort "Loop broke: #{e.message}"
```

---

<div class="post-metadata">

**Author:** ![haarts](https://avatars.discourse-cdn.com/v4/letter/h/8797f3/32.png) [@haarts](https://forum.crystal-lang.org/u/haarts)\
**Post date:** [September 17, 2021, 8:11am UTC](https://forum.crystal-lang.org/t/exception-inside-a-spawn-block-should-crash-the-program/3853/3 "2021-09-17T08:11:38Z")

</div>

That was the missing piece in my understanding! An exception only crashes the fiber. That makes total sense.  
I’ve modified my code according to your suggestion and that works like a charm. Clever using a channel like that.

As a cherry on the pie I learned about `abort`. Thank you, you’ve made my morning.

---

<div class="post-metadata">

**Author:** ![yxhuvud](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/yxhuvud/32/27_2.png) [@yxhuvud](https://forum.crystal-lang.org/u/yxhuvud)\
**Post date:** [September 17, 2021, 8:26pm UTC](https://forum.crystal-lang.org/t/exception-inside-a-spawn-block-should-crash-the-program/3853/4 "2021-09-17T20:26:15Z")

</div>

When it comes to desired behavior as opposed to current behavior, I agree that exceptions should bubble up (by default).

Changing so that exceptions bubble up would require a hierarchical structure of spawned fibers though, as otherwise there will be no guarantee that there is somewhere to bubble to. That hierarchy is basically issue #6468, which is no small task to implement.

That could also do away with having to bother with waiting on a channel, which would be a nice win.

---

<div class="post-metadata">

**Author:** ![rogerdpack](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/rogerdpack/32/117_2.png) [@rogerdpack](https://forum.crystal-lang.org/u/rogerdpack)\
**Post date:** [September 17, 2021, 9:46pm UTC](https://forum.crystal-lang.org/t/exception-inside-a-spawn-block-should-crash-the-program/3853/5 "2021-09-17T21:46:33Z")

</div>

Maybe crystal could add an option like ruby’s  
Thread.abort\_on\_exception? Not sure if it would be useful but… typically you _want_ to know when a thread dies unexpectedly? :)

---

<div class="post-metadata">

**Author:** ![straight-shoota](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/straight-shoota/32/36_2.png) [@straight-shoota](https://forum.crystal-lang.org/u/straight-shoota)\
**Post date:** [September 18, 2021, 7:12am UTC](https://forum.crystal-lang.org/t/exception-inside-a-spawn-block-should-crash-the-program/3853/6 "2021-09-18T07:12:55Z")

</div>

You could use a helper like this:

```auto
def spawn_with_abort(&block)
  spawn do
    block.call
  rescue exc
    exc.inspect_with_backtrace(STDERR)
    abort
  end
end

```

---

<div class="post-metadata">

**Author:** ![rogerdpack](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/rogerdpack/32/117_2.png) [@rogerdpack](https://forum.crystal-lang.org/u/rogerdpack)\
**Post date:** [October 1, 2021, 5:52pm UTC](https://forum.crystal-lang.org/t/exception-inside-a-spawn-block-should-crash-the-program/3853/7 "2021-10-01T17:52:29Z")

</div>

Possibly related, I believe when a fiber dies it outputs something to stderr. Is there any way to change that behavior?

---

<div class="post-metadata">

**Author:** ![straight-shoota](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/straight-shoota/32/36_2.png) [@straight-shoota](https://forum.crystal-lang.org/u/straight-shoota)\
**Post date:** [October 1, 2021, 7:23pm UTC](https://forum.crystal-lang.org/t/exception-inside-a-spawn-block-should-crash-the-program/3853/8 "2021-10-01T19:23:59Z")

</div>

Not globally. I suppose you can override `Fiber#run` to change that. But I don’t think that’s a good idea because there are fibers not initiated by your application.  
Best way to deal with that is similar to what I showed in my previous comment: Rescue the exception in the spawned proc and handle it there.  
Or wait for [[RFC] Structured Concurrency · Issue #6468 · crystal-lang/crystal · GitHub](https://github.com/crystal-lang/crystal/issues/6468)
