cgo & long jump

110 views
Skip to first unread message

pa...@cpan.org

unread,
Dec 9, 2019, 11:57:29 AM12/9/19
to golan...@googlegroups.com
Hello!

I would like to ask some technical question about cgo and long jumps.

In Go I have written shared library which exports C API and therefore
can be called by other C applications. This my library is compiling with
cgo, more precisely via: go build -buildmode=c-shared -compiler gc

Now I would like to call from my Go library some C function which may
call longjmp(). And setjmp() was already called by application which is
using my Go library.

It is possible to call from Go C function which calls longjmp() which
jumps outside of that my Go library? What would happen with Go garbage
collector and "defer" code?

To imagine, whole stack looks like this:

+------------------------------------------+
| C application |
| main(): |
| call setjmp() |
| call f1() from Go library |
| ... |
+------------------------------------------+
| Go library with exported C f1() function |
| f1(): |
| do something in Go |
| call f2() from C library |
| ... |
| return from f1() |
+------------------------------------------+
| C library with exported f2() function |
| f2(): |
| do something in C |
| if error call longjmp() |
| else return from f2() |
+------------------------------------------+

And if longjmp() is called then it jumps to main() where setjmp() was
called. So effectively f1() function (in Go) does not return.

Ian Lance Taylor

unread,
Dec 9, 2019, 1:19:02 PM12/9/19
to pa...@cpan.org, golang-nuts
I'm pretty sure that won't work at all. Sorry.

Certainly no Go deferred functions will be run. I don't think this
would break the garbage collector as such, but I expect that it would
break the Go scheduler. In the best case you'll be left with a
dangling goroutine that will never be run and never go away.

Ian

pa...@cpan.org

unread,
Dec 9, 2019, 1:30:58 PM12/9/19
to Ian Lance Taylor, golang-nuts
Hi Ian! Thank you for your answer.

I was trying to find any resource on Internet about long jumps and
"import C" but neither in official Go documentation nor in any other
blog post is written about it.

There are many resources how Go is (fully) compatible with C and can
call C functions, but absolutely zero information how it is implemented
nor what would happen with such core feature of C language as long jumps
or signals.

> Certainly no Go deferred functions will be run. I don't think this
> would break the garbage collector as such, but I expect that it would
> break the Go scheduler. In the best case you'll be left with a
> dangling goroutine that will never be run and never go away.

So should I interpret your answer as long jumps are not supported and
caller of C function from Go must ensure that called C function would
not call longjmp()?


And another interesting question, it is possible to call longjmp() from
Go code? To throw C exception back to the main C application.

Michael Jones

unread,
Dec 9, 2019, 2:25:16 PM12/9/19
to pa...@cpan.org, Ian Lance Taylor, golang-nuts
The longjmp() facility is a wild, dangerous, improper, and popular mechanism. It's premise is that the app can go back in time, like you waking up last week with no knowledge of what happened since then. If you can follow that analogy, then imagine your surprise when external things you did last week--ordering from Amazon or getting married--start showing up in your life by surprise or you fail to show up as you should in theirs, through ignorance, with consequences either way. So it will be with the relationship between C and Go. You'll leave many things hanging or abandoned when you longump() back to your application's youth.

(I imagine this is colorful terms, like getting a text on my phone reading "setjmp() returned 1" and having a paroxysm of imagined crises like "maybe I got married, had a daughter, and she's waiting for me now at daycare! OMG, I just don't know.")

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/20191209183039.khrexxnpedzitepy%40pali.


--
Michael T. Jones
michae...@gmail.com

Robert Engels

unread,
Dec 9, 2019, 2:25:32 PM12/9/19
to pa...@cpan.org, Ian Lance Taylor, golang-nuts

That usage of setjmp and longjmp are pretty much banned in modern C by every linter. You can only call setjmp/longjmp within the current call stack (at least that's my understanding) - intermixing the context switch to Go would not be correct.

Just have a wrapper on f2() that takes the setjmp address() and set it and call f2().

Dan Kortschak

unread,
Dec 9, 2019, 4:37:22 PM12/9/19
to Michael Jones, pa...@cpan.org, Ian Lance Taylor, golang-nuts
This breaks my already fairly tenuous grasp of the progression of time;
what do you mean by since "since then" when that event is a personal
that is in the past (do you mean between going to sleep in the future
and waking up in the past).

Time [travel] is hard.

Ian Lance Taylor

unread,
Dec 9, 2019, 6:55:49 PM12/9/19
to pa...@cpan.org, golang-nuts
On Mon, Dec 9, 2019 at 10:30 AM <pa...@cpan.org> wrote:
>
> So should I interpret your answer as long jumps are not supported and
> caller of C function from Go must ensure that called C function would
> not call longjmp()?

Correct: Go code should not call C code that calls longjmp. (Well,
it's OK to call C code that calls setjmp and then calls longjmp back
to that setjmp; what's not OK is using longjmp to jump across or out
of the Go code.)

> And another interesting question, it is possible to call longjmp() from
> Go code? To throw C exception back to the main C application.

No.

Ian

pa...@cpan.org

unread,
Dec 10, 2019, 5:20:29 AM12/10/19
to Ian Lance Taylor, golang-nuts
On Monday 09 December 2019 15:55:18 Ian Lance Taylor wrote:
> On Mon, Dec 9, 2019 at 10:30 AM <pa...@cpan.org> wrote:
> >
> > So should I interpret your answer as long jumps are not supported and
> > caller of C function from Go must ensure that called C function would
> > not call longjmp()?
>
> Correct: Go code should not call C code that calls longjmp. (Well,
> it's OK to call C code that calls setjmp and then calls longjmp back
> to that setjmp; what's not OK is using longjmp to jump across or out
> of the Go code.)

One small suggestion: Could you put this information into cgo
documentation? I think that this should be documented.

> > And another interesting question, it is possible to call longjmp() from
> > Go code? To throw C exception back to the main C application.
>
> No.

Thank you for answers!

Ian Lance Taylor

unread,
Dec 10, 2019, 9:31:24 AM12/10/19
to pa...@cpan.org, golang-nuts
On Tue, Dec 10, 2019 at 2:20 AM <pa...@cpan.org> wrote:
>
> On Monday 09 December 2019 15:55:18 Ian Lance Taylor wrote:
> > On Mon, Dec 9, 2019 at 10:30 AM <pa...@cpan.org> wrote:
> > >
> > > So should I interpret your answer as long jumps are not supported and
> > > caller of C function from Go must ensure that called C function would
> > > not call longjmp()?
> >
> > Correct: Go code should not call C code that calls longjmp. (Well,
> > it's OK to call C code that calls setjmp and then calls longjmp back
> > to that setjmp; what's not OK is using longjmp to jump across or out
> > of the Go code.)
>
> One small suggestion: Could you put this information into cgo
> documentation? I think that this should be documented.

Personally I think documentation in this e-mail thread or a blog post
is sufficient. As Michael said upthread, all kinds of things break
when using setjmp/longjmp. Essentially no complex library supports
calling longjmp across library functions.

Ian
Reply all
Reply to author
Forward
0 new messages