Segmentation fault when linking with Go library from a C++ program

46 views
Skip to first unread message

ine...@gmail.com

unread,
Aug 18, 2017, 8:48:30 AM8/18/17
to golang-nuts
I have a C++ application from which I need to call Go functions. I noticed that the application crashes
on exit from the `main` function (with only a "Segmentation fault" message, no core dump and neither
did gdb show anything useful) about once in three runs. Then I added the `-fsanitize=address` flag to
the build and started to see messages such as these:

=================================================================
==8006==ERROR: LeakSanitizer: detected memory leaks


Direct leak of 24 byte(s) in 1 object(s) allocated from:
   
#0 0x7f9ef4571602 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x98602)
   
#1 0x40421d in x_cgo_thread_start /usr/local/go/src/runtime/cgo/gcc_util.c:15
   
#2 0x42bcff in runtime.startm /usr/local/go/src/runtime/proc.go:1698
   
#3 0x42c059 in runtime.wakep /usr/local/go/src/runtime/proc.go:1779
   
#4 0x42f179 in runtime.newproc1 /usr/local/go/src/runtime/proc.go:2958
   
#5 0x4490d2 in runtime.newproc.func1 /usr/local/go/src/runtime/proc.go:2845
   
#6 0x4498d1 in runtime.systemstack /usr/local/go/src/runtime/asm_amd64.s:327


Direct leak of 24 byte(s) in 1 object(s) allocated from:
   
#0 0x7f9ef4571602 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x98602)
   
#1 0x40421d in x_cgo_thread_start /usr/local/go/src/runtime/cgo/gcc_util.c:15
   
#2 0x4488a7 in runtime.main.func1 /usr/local/go/src/runtime/proc.go:126
   
#3 0x4498d1 in runtime.systemstack /usr/local/go/src/runtime/asm_amd64.s:327


Direct leak of 24 byte(s) in 1 object(s) allocated from:
   
#0 0x7f9ef4571602 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x98602)
   
#1 0x40421d in x_cgo_thread_start /usr/local/go/src/runtime/cgo/gcc_util.c:15
   
#2 0x42bcff in runtime.startm /usr/local/go/src/runtime/proc.go:1698
   
#3 0x42bdd6 in runtime.handoffp /usr/local/go/src/runtime/proc.go:1725
   
#4 0x42c1f4 in runtime.stoplockedm /usr/local/go/src/runtime/proc.go:1793
   
#5 0x42d5da in runtime.schedule /usr/local/go/src/runtime/proc.go:2180
   
#6 0x42d730 in runtime.park_m /usr/local/go/src/runtime/proc.go:2285
   
#7 0x449842 in runtime.mcall /usr/local/go/src/runtime/asm_amd64.s:269


SUMMARY
: AddressSanitizer: 72 byte(s) leaked in 3 allocation(s).

or

=================================================================
==28395==ERROR: LeakSanitizer: detected memory leaks


Direct leak of 24 byte(s) in 1 object(s) allocated from:
   
#0 0x7f562b171602 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x98602)
   
#1 0x403a0d in x_cgo_thread_start /usr/local/go/src/runtime/cgo/gcc_util.c:15
   
#2 0x42b4ef in runtime.startm /usr/local/go/src/runtime/proc.go:1698
   
#3 0x42b5c6 in runtime.handoffp /usr/local/go/src/runtime/proc.go:1725
   
#4 0x42b9e4 in runtime.stoplockedm /usr/local/go/src/runtime/proc.go:1793
   
#5 0x42cdca in runtime.schedule /usr/local/go/src/runtime/proc.go:2180
   
#6 0x42cf20 in runtime.park_m /usr/local/go/src/runtime/proc.go:2285
   
#7 0x449032 in runtime.mcall /usr/local/go/src/runtime/asm_amd64.s:269


Direct leak of 24 byte(s) in 1 object(s) allocated from:
   
#0 0x7f562b171602 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x98602)
   
#1 0x403a0d in x_cgo_thread_start /usr/local/go/src/runtime/cgo/gcc_util.c:15
   
#2 0x42b4ef in runtime.startm /usr/local/go/src/runtime/proc.go:1698
   
#3 0x42b849 in runtime.wakep /usr/local/go/src/runtime/proc.go:1779
   
#4 0x42c8b4 in runtime.resetspinning /usr/local/go/src/runtime/proc.go:2141
   
#5 0x42cc09 in runtime.schedule /usr/local/go/src/runtime/proc.go:2229
   
#6 0x42a2db in runtime.mstart1 /usr/local/go/src/runtime/proc.go:1189
   
#7 0x42a1f5 in runtime.mstart /usr/local/go/src/runtime/proc.go:1149
   
#8 0x403a62  (/home/peter/work/tmp/minimal-cgo/a.out+0x403a62)


SUMMARY
: AddressSanitizer: 48 byte(s) leaked in 2 allocation(s).

but most often just this one:

=================================================================
==17138==ERROR: LeakSanitizer: detected memory leaks


Direct leak of 24 byte(s) in 1 object(s) allocated from:
   
#0 0x7f15bfe0e602 in malloc (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x98602)
   
#1 0x403eed in x_cgo_thread_start /usr/local/go/src/runtime/cgo/gcc_util.c:15
   
#2 0x448577 in runtime.main.func1 /usr/local/go/src/runtime/proc.go:126
   
#3 0x4495a1 in runtime.systemstack /usr/local/go/src/runtime/asm_amd64.s:327


SUMMARY
: AddressSanitizer: 24 byte(s) leaked in 1 allocation(s).

I reduced the code which can reproduce these to the three attached files. With this reduced code I can see the failures
a lot less often though. Sometimes I can see the error quite quickly, but sometimes I need to let the `run.sh` script run
for more than a minute.

I have tested with go1.8, go1.8.3 and go1.9rc2 (linux amd64) with the same results.

~ > g++ --version
g
++ (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609

Do I need to call some cgo function to properly de-initialize go when exiting the main function?

Regards,

Peter


go_code.go
main.cpp
run.sh

Ian Lance Taylor

unread,
Aug 18, 2017, 9:44:04 AM8/18/17
to ine...@gmail.com, golang-nuts
On Fri, Aug 18, 2017 at 4:21 AM, <ine...@gmail.com> wrote:
>
> I have a C++ application from which I need to call Go functions. I noticed
> that the application crashes
> on exit from the `main` function (with only a "Segmentation fault" message,
> no core dump and neither
> did gdb show anything useful) about once in three runs.

That is a problem. When you say that gdb doesn't show anything
useful, what do you mean? Does it at least show where the
segmentation fault is occurring?


> Then I added the
> `-fsanitize=address` flag to
> the build and started to see messages such as these:

These are not problems. These just mean that some of Go's internal
libraries are not using the address sanitizer hooks. The memory will
be freed, and even it weren't, a few small space leaks could not cause
a segmentation violation.


> I reduced the code which can reproduce these to the three attached files. With this reduced code I can see the failures
> a lot less often though. Sometimes I can see the error quite quickly, but sometimes I need to let the `run.sh` script run
> for more than a minute.

Thanks for the test case. Unfortunately, I was unable to recreate the problem.

Looking at the code, it looks like the problem may be related to
exiting the program while the Go runtime is still being initialized.
I can't think of any reason why that would be a problem, but I also
can't think of anything else. What C library are you using? What
version?


> Do I need to call some cgo function to properly de-initialize go when exiting the main function?

No. But if I'm right that this is related to exiting while the
runtime is being initialized, then a workaround would be to call any
Go function on exit, even a Go function that does nothing. Calling a
Go function will automatically wait until runtime initialization is
complete.


Ian

Konstantin Khomoutov

unread,
Aug 18, 2017, 9:45:19 AM8/18/17
to ine...@gmail.com, golang-nuts
On Fri, Aug 18, 2017 at 04:21:27AM -0700, ine...@gmail.com wrote:
> I have a C++ application from which I need to call Go functions. I noticed
> that the application crashes
> on exit from the `main` function (with only a "Segmentation fault" message,
> no core dump

Not to answer your question, but these days core dumping is usually
disabled by default through the "soft" limit, but it's possible to
enable it, say, by executing

ulimit -c unlimited

before starting the problem.

[...]

ine...@gmail.com

unread,
Aug 18, 2017, 12:48:26 PM8/18/17
to golang-nuts, ine...@gmail.com
I think I found it, I was wrong above where I said that at first I did not have address
sanitizer enabled. Seems when I disable it, I no longer see any "Segmentation fault"
messages nor memory leak reports from the sanitizer (obviously).


That is a problem.  When you say that gdb doesn't show anything 
useful, what do you mean?  Does it at least show where the 
segmentation fault is occurring? 

When I run it through gdb with memory sanitizer enabled I only see the memory leak
reports. Never the "Segmentation fault" message.

When I don't run it through gdb, I sometimes see the memory leak report, but sometimes
the "Segmentation fault" message which looks like this:

# ./a.out
Options:
 
--help                Produce this help message
 
--repo arg (=./repo)  Path to the repository

Segmentation fault
#

Where the "Options:..." part is my output but the "Segmentation fault" line is not mine.

enable it, say, by executing 
  ulimit -c unlimited 
before starting the problem. 

Thanks for the hint, but I already had it enabled.

What C library are you using?

# ldd a.out
 linux
-vdso.so.1 =>  (0x00007fffdd70e000)
 libasan
.so.2 => /usr/lib/x86_64-linux-gnu/libasan.so.2 (0x00007f636ebfa000)
 libevent
-2.0.so.5 => /usr/lib/x86_64-linux-gnu/libevent-2.0.so.5 (0x00007f636e9b4000)
 libevent_pthreads
-2.0.so.5 => /usr/lib/x86_64-linux-gnu/libevent_pthreads-2.0.so.5 (0x00007f636e7b0000)
 libboost_program_options
.so.1.58.0 => /usr/lib/x86_64-linux-gnu/libboost_program_options.so.1.58.0 (0x00007f636e532000)
 libstdc
++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f636e1b0000)
 libgcc_s
.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f636df99000)
 libpthread
.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f636dd7c000)
 libc
.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f636d9b2000)
 libdl
.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f636d7ad000)
 libm
.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f636d4a4000)
 libevent_core
-2.0.so.5 => /usr/lib/x86_64-linux-gnu/libevent_core-2.0.so.5 (0x00007f636d27a000)
 
/lib64/ld-linux-x86-64.so.2 (0x000056445740e000)
 
But if I'm right that this is related to exiting while the 
runtime is being initialized, then a workaround would be to call any 
Go function on exit, even a Go function that does nothing.

This is interesting, when I call a "go_do_nothing()" function right before `return 0;` from the C++ main function
, run the executable NOT through gdb, and with memory sanitizer enabled, I only see the "Segmentation fault"
messages. Very consistently and never any memory leak reports.

When I run it through gdb however I do sometimes see the mem leaks, never any crash though.

I think it looks like the sanitizer fault now. I'll try to upgrade and come back.
Reply all
Reply to author
Forward
0 new messages