# When using thread\_signal(ThreadID, throw(my\_exception)): foreign predicate system:\>/2 did not clear exception

**URL:** <https://swi-prolog.discourse.group/t/when-using-thread-signal-threadid-throw-my-exception-foreign-predicate-system-2-did-not-clear-exception/4027>\
**Category:** Help!\
**Created:** [June 4, 2021, 3:18pm UTC](https://swi-prolog.discourse.group/t/when-using-thread-signal-threadid-throw-my-exception-foreign-predicate-system-2-did-not-clear-exception/4027 "2021-06-04T15:18:27Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![ericzinda](https://avatars.discourse-cdn.com/v4/letter/e/b3f665/32.png) [@ericzinda](https://swi-prolog.discourse.group/u/ericzinda)\
**Post date:** [June 4, 2021, 3:18pm UTC](https://swi-prolog.discourse.group/t/when-using-thread-signal-threadid-throw-my-exception-foreign-predicate-system-2-did-not-clear-exception/4027/1 "2021-06-04T15:18:27Z")

</div>

I am trying to support cancelling a long running goal in a thread. Moreover, I want to have the goal automatically cancelled by a timeout, but support manual cancellation earlier as well.

I started by running `sleep(20000)` in a thread started by thread\_create/3 with the thread alias `goal1`.

I then try to cancel it by calling:

```prolog
% Note that I don't throw abort/0 even though that is a more reliable
% "mostly uncatchable" exception because I want the thread to stick
% around to run more goals
thread_signal(goal1, throw(cancel_goal))

```

This works as expected and the exception bubbles up the thread properly.

However, if I wrap the goal first in call\_with\_time\_limit/2 like this:

```prolog
call_with_time_limit(10, sleep(20000))

```

and then cancel it the same way:

```prolog
thread_signal(goal1, throw(cancel_goal))

```

I get this error spit out to the top level:

```prolog
Thread 4 (goal1): foreign predicate system:>/2 did not clear exception: 
	cancel_goal

```

and the error that bubbles up is actually `time_limit_exceeded`, which is the exception that would be thrown normally by the `call_with_time_limit/2` predicate on timeout (even though I am well before the timeout).

Am I doing something incorrectly?

[Edit: Here’s the actual code I’m using in case that helps. The issue seems timing related since it doesn’t always happen…]

```prolog
% A successful test session, I don't seem to be able to repro now...
?- startGoalThread.
true.

?- sendGoalToGoalThread(20000, sleep(10000), []).
true.

?- cancelGoal.
error(cancel_goal)
true.

?- sendGoalToGoalThread(20000, sleep(1), []).
true.

?- cancelGoal.
true([[]])
true.

```

```prolog
startGoalThread :-
   thread_self(CommunicationThreadID),
   thread_create(
                goal_thread(CommunicationThreadID),
                _,
                [alias(goal1)]
            ).

sendGoalToGoalThread(Timeout, Goal, BindingList) :-
    thread_send_message(goal1, goal(Goal, BindingList, Timeout)).

cancelGoal :-
    % Insert a known exception into the thread
    thread_signal(goal1, throw(cancel_goal)),
    % Wait for whatever response occurs
    thread_self(SelfID),
    thread_get_message(SelfID, result(Result)),
    writeln(Result).

% The worker predicate for the Goal thread. Looks for a message, processes it, then recurses.
% Goals always run in the same thread in case the user is setting thread
% local information.
goal_thread(RespondToThreadID) :-
    thread_self(SelfID),
    thread_get_message(SelfID, goal(Goal, BindingList, QueryTimeout)),
    (
        % Exceptions that occur while executing the goal should be returned
        % run all commands in the context of the 'user' module so it acts like
        % the Prolog top level
        QueryTimeout == -1
        ->
        (
            ThreadGoal = catch(findall(BindingList, @(Goal, user), Answers), E, true)
        )
        ;
        (
            ThreadGoal = catch(call_with_time_limit(QueryTimeout, findall(BindingList, @(Goal, user), Answers)), E, true)
        )
    ),
    debug(prologServer(command), "Executing Goal: ~w", [Goal]),
    ThreadGoal,
    (
        var(E)
        ->
        (
            debug(prologServer(command), "Completed Goal: ~w", [Goal]),
            Answers == []
            ->
            (
                thread_send_message(RespondToThreadID, result(false))
            )
            ;
            (
                thread_send_message(RespondToThreadID, result(true(Answers)))
            )
        )
        ;
        (
            debug(prologServer(command), "Exception in Goal: ~w, ~w", [Goal, E]),
            thread_send_message(RespondToThreadID, result(error(E)))
        )
    ),
    % Use tail recursion to avoid growing the stack
    goal_thread(RespondToThreadID).

```

---

<div class="post-metadata">

**Author:** ![ericzinda](https://avatars.discourse-cdn.com/v4/letter/e/b3f665/32.png) [@ericzinda](https://swi-prolog.discourse.group/u/ericzinda)\
**Post date:** [June 17, 2021, 9:17pm UTC](https://swi-prolog.discourse.group/t/when-using-thread-signal-threadid-throw-my-exception-foreign-predicate-system-2-did-not-clear-exception/4027/2 "2021-06-17T21:17:00Z")

</div>

I can now reliably reproduce getting this message when shutting down using `halt(abort)`:

> Thread 6 (language\_server1\_conn2\_comm): foreign predicate system:\>/2 did not clear exception: $aborted

It looks like it is output as a system “warning” (based on the color of the text 🙂 )

@jan Is this something expected and not to worry about? or a bug I should log?

Worst case I’d love to at least get rid of the warning because it happens during normal shutdown of the code I’m working on and it at least _looks_ scary in the logs.

---

<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:** [June 18, 2021, 6:31am UTC](https://swi-prolog.discourse.group/t/when-using-thread-signal-threadid-throw-my-exception-foreign-predicate-system-2-did-not-clear-exception/4027/3 "2021-06-18T06:31:20Z")

</div>

It should be fixed. It mostly means an exception is lost. That doesn’t need to be terrible, surely when it is part of the shutdown anyway 🙂 When I’m at evaluation and testing I’ll probably find and fix it. These aren’t very hard to fix: set an gdb breakpoint on PL\_raise\_exception(), possibly with some conditions, examine the context and where the `FALSE` return code is not propagated.
