# Catching thread exception

**URL:** <https://swi-prolog.discourse.group/t/catching-thread-exception/4782>\
**Category:** Help!\
**Created:** [December 17, 2021, 8:15pm UTC](https://swi-prolog.discourse.group/t/catching-thread-exception/4782 "2021-12-17T20:15:26Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![swi](https://avatars.discourse-cdn.com/v4/letter/s/51bf81/32.png) [@swi](https://swi-prolog.discourse.group/u/swi)\
**Post date:** [December 17, 2021, 8:15pm UTC](https://swi-prolog.discourse.group/t/catching-thread-exception/4782/1 "2021-12-17T20:15:26Z")

</div>

```prolog
6 ?- thread_create(catch(sleep(0.5),_,true),T,[detached(true)]), thread_signal(T,abort).
T = <thread>(4,0x5591a0b70050).

Warning: [Thread 4] Thread running "'$thread_init'" died on exception: Execution Aborted

```

I would expect the exception to be caught and the message not printed, am I missing something?

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [December 18, 2021, 8:47am UTC](https://swi-prolog.discourse.group/t/catching-thread-exception/4782/2 "2021-12-18T08:47:52Z")

</div>

Who should catch the exception? Detached threads are really that: they are no longer supervised by anything. They die without leaving a trace as they have no place to report to. Mostly for debugging it prints exceptions or failure. If you do not want that, wrap the goal in catch/3 and send the exception somewhere. Note that applications can use prolog\_listen/3 to keep overall track of created and terminated threads. Not sure how useful that is.

P.s. Possibly you think a dying thread should cause an asynchronous exception in the thread that created the thread? Note that in the POSIX thread world the creator is irrelevant and may decide to terminate before its children (that notion doesn’t exist anyway).

---

<div class="post-metadata">

**Author:** ![swi](https://avatars.discourse-cdn.com/v4/letter/s/51bf81/32.png) [@swi](https://swi-prolog.discourse.group/u/swi)\
**Post date:** [December 18, 2021, 12:21pm UTC](https://swi-prolog.discourse.group/t/catching-thread-exception/4782/3 "2021-12-18T12:21:37Z")

</div>

> [@jan](#):
>
> If you do not want that, wrap the goal in [catch/3](https://www.swi-prolog.org/pldoc/doc_for?object=catch/3) and send the exception somewhere.

I thought that is what I did above?

```prolog
6 ?- thread_create(catch(sleep(0.5),_,true),T,[detached(true)]), thread_signal(T,abort).

```

Notice the catch around the sleep. Am I missing something?

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [December 18, 2021, 2:20pm UTC](https://swi-prolog.discourse.group/t/catching-thread-exception/4782/4 "2021-12-18T14:20:44Z")

</div>

You can’t catch abort. Well, you can but the recovery handler is wrapped in `call_cleanup(Handler, abort)`. To avoid this don’t use detached. That is also correct as apparently you do want to keep control over the thread. Now, you kill a thread forcefully by injecting an abort and use thread\_join/2.

---

<div class="post-metadata">

**Author:** ![swi](https://avatars.discourse-cdn.com/v4/letter/s/51bf81/32.png) [@swi](https://swi-prolog.discourse.group/u/swi)\
**Post date:** [December 18, 2021, 4:45pm UTC](https://swi-prolog.discourse.group/t/catching-thread-exception/4782/5 "2021-12-18T16:45:38Z")

</div>

It doesn’t catch any exception, the following also prints the warning also.

```prolog
?- thread_create(catch(sleep(0.5),_,true),T,[detached(true)]),
    thread_signal(T,throw(done)). % notice the exception is not abort
T = <thread>(4,0x562b28a93680).

Warning: [Thread 4] Thread running "'$thread_init'" died on exception: Unknown message: done

```

> [@jan](#):
>
> To avoid this don’t use detached. That is also correct as apparently you do want to keep control over the thread. Now, you kill a thread forcefully by injecting an abort and use [thread\_join/2](https://www.swi-prolog.org/pldoc/doc_for?object=thread_join/2).

Yes, I can do that too.

The use case is rather uncommon I guess, it is just a dummy thread used in one test, and in another test I wanted to make sure the thread was dead because the alias is reused in the second test and I just wanted to get rid of the message.

I will just not use detached on the first test and join the thread.

Nonetheless, thread\_create/3 docs mention that one can use catch/3 to catch the exception in a detached thread (this is why I kept the detached thread):

> If a detached thread dies due to failure or exception of the initial goal, the thread prints a message using [print\_message/2](https://www.swi-prolog.org/pldoc/man?predicate=print_message/2). If such termination is considered normal, the code must be wrapped using [ignore/1](https://www.swi-prolog.org/pldoc/man?predicate=ignore/1) and/or [catch/3](https://www.swi-prolog.org/pldoc/man?predicate=catch/3) to ensure successful completion.

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [December 18, 2021, 5:03pm UTC](https://swi-prolog.discourse.group/t/catching-thread-exception/4782/6 "2021-12-18T17:03:55Z")

</div>

The problem is that your signal arrives before the catch/3 is started, i.e., it arrives during the thread initialization. Try this:

```prolog
?- thread_create(catch(sleep(0.5),_,true),T,[detached(true)]),
   sleep(0.1), % give some time to get into the catch/3
   thread_signal(T,throw(done)).
T = <thread>(3,0x559bf5930320).

```

Of course, using sleep/1 to get the timing right is bad. Normally you’d send a message to your creator when you are ready and the creator needs to wait for that.

As for tests, all SWI-Prolog tests that create threads join these before the test completes.

---

<div class="post-metadata">

**Author:** ![swi](https://avatars.discourse-cdn.com/v4/letter/s/51bf81/32.png) [@swi](https://swi-prolog.discourse.group/u/swi)\
**Post date:** [December 18, 2021, 5:45pm UTC](https://swi-prolog.discourse.group/t/catching-thread-exception/4782/7 "2021-12-18T17:45:46Z")

</div>

> [@jan](#):
>
> The problem is that your signal arrives before the [catch/3](https://www.swi-prolog.org/pldoc/doc_for?object=catch/3) is started, i.e., it arrives during the thread initialization.

Ahh yes, that was it.

> [@jan](#):
>
> Of course, using [sleep/1](https://www.swi-prolog.org/pldoc/doc_for?object=sleep/1) to get the timing right is bad. Normally you’d send a message to your creator when you are ready and the creator needs to wait for that.

In this case I just need a dummy thread to take up the alias name during the test, so I’ll just abort it and join it. The timing is not really important because I’ll abort the dummy thread when the test has completed.

Thanks for your help!
