# What happens when you throw an error from a \`@cfunction\`?

**URL:** <https://discourse.julialang.org/t/what-happens-when-you-throw-an-error-from-a-cfunction/71510>\
**Category:** Internals & Design\
**Created:** [November 15, 2021, 4:57pm UTC](https://discourse.julialang.org/t/what-happens-when-you-throw-an-error-from-a-cfunction/71510 "2021-11-15T16:57:42Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![simonbyrne](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/simonbyrne/32/19_2.png) [@simonbyrne](https://discourse.julialang.org/u/simonbyrne)\
**Post date:** [November 15, 2021, 4:57pm UTC](https://discourse.julialang.org/t/what-happens-when-you-throw-an-error-from-a-cfunction/71510/1 "2021-11-15T16:57:42Z")

</div>

If I define a C-callable function pointer (via `@cfunction`) which can internally throw an error, and then perform a `ccall` which would then invoke the function and trigger the error, what actually happens? I assume it does some sort of `longjmp` back into the Julia runtime, but I don’t actually know for sure.

---

<div class="post-metadata">

**Author:** ![jameson](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jameson/32/23_2.png) [@jameson](https://discourse.julialang.org/u/jameson)\
**Post date:** [November 15, 2021, 7:51pm UTC](https://discourse.julialang.org/t/what-happens-when-you-throw-an-error-from-a-cfunction/71510/2 "2021-11-15T19:51:06Z")

</div>

It is undefined. You destroy the state of the library you escaped from (via the throw), which may then do anything.

---

<div class="post-metadata">

**Author:** ![simonbyrne](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/simonbyrne/32/19_2.png) [@simonbyrne](https://discourse.julialang.org/u/simonbyrne)\
**Post date:** [November 16, 2021, 6:11am UTC](https://discourse.julialang.org/t/what-happens-when-you-throw-an-error-from-a-cfunction/71510/3 "2021-11-16T06:11:48Z")

</div>

Okay, so we shouldn’t do that (and that should probably be documented), but what actually does happen?

---

<div class="post-metadata">

**Author:** ![c42f](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/c42f/32/52842_2.png) [@c42f](https://discourse.julialang.org/u/c42f)\
**Post date:** [November 16, 2021, 10:01am UTC](https://discourse.julialang.org/t/what-happens-when-you-throw-an-error-from-a-cfunction/71510/4 "2021-11-16T10:01:41Z")

</div>

`throw` and `catch` are currently implemented via setjmp/longjmp or similar (actually custom assembly on windows and `sigsetjmp`/`siglongjmp` elsewhere)

What I expect to happen is as you guessed — you’ll `longjmp` back into the Julia landing pad and resume execution from there. It might even work if the library you’re jumping out of doesn’t do any resource management, or alternatively it may also work if the library _does_ do resource management in the same way that the Julia runtime does (ie, uses the Julia GC to allocate memory and manually roots resources as part of its operation).

_However_… I’m unsure whether the code emitted by `ccall` assumes that it won’t be jumped over. Looking briefly I can’t see any such assumptions in the code but they could be there.

---

<div class="post-metadata">

**Author:** ![odow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/odow/32/28685_2.png) [@odow](https://discourse.julialang.org/u/odow)\
**Post date:** [November 16, 2021, 6:23pm UTC](https://discourse.julialang.org/t/what-happens-when-you-throw-an-error-from-a-cfunction/71510/5 "2021-11-16T18:23:30Z")

</div>

Here’s what I did in GLPK to work-around this:

The cfunction has a try-catch to trap errors. In the catch, we gracefully exit from C tidying up after ourselves, and save the error for later  
[https://github.com/jump-dev/GLPK.jl/blob/5cee5af5cbd78ba074fa391f04f99ac8daafda92/src/MOI\_wrapper/MOI\_wrapper.jl#L209-L235](https://github.com/jump-dev/GLPK.jl/blob/5cee5af5cbd78ba074fa391f04f99ac8daafda92/src/MOI_wrapper/MOI_wrapper.jl#L209-L235)  
Then in the Julia function that calls everything, we run the ccall, and then re-throw the error if our cfunction trapped one:  
[https://github.com/jump-dev/GLPK.jl/blob/5cee5af5cbd78ba074fa391f04f99ac8daafda92/src/MOI\_wrapper/MOI\_wrapper.jl#L1382-L1405](https://github.com/jump-dev/GLPK.jl/blob/5cee5af5cbd78ba074fa391f04f99ac8daafda92/src/MOI_wrapper/MOI_wrapper.jl#L1382-L1405)
