Skip to content

cmd/link: exporting free c function from c-shared library hangs executable with that library LD_PRELOADed  #26184

Open
@tumdum

Description

@tumdum

What version of Go are you using (go version)?

go version go1.10.2 linux/amd64

Does this issue reproduce with the latest release?

No idea

What operating system and processor architecture are you using (go env)?

GOARCH="amd64"
GOBIN=""
GOCACHE="/home/tumdum/.cache/go-build"
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/home/tumdum/go"
GORACE=""
GOROOT="/usr/local/go"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build872026307=/tmp/go-build -gno-record-gcc-switches"

What did you do?

I've tried to intercept C function free via LD_PRELOAD.

$ cat main.go 
package main

import "unsafe"
import "C"

//export free
func free(p unsafe.Pointer) {}
func main()                 {}
$ go build -o fake_malloc.so -buildmode=c-shared main.go
$ LD_PRELOAD=./fake_malloc.so yes
# in never prints nor ends

# in other shell:
$ sudo gdb -q -batch -ex "attach $(pidof yes)" -ex "thread apply all bt"
[New LWP 7421]
Loading Go Runtime support.
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
0x00007fa6355d1072 in futex_wait_cancelable (private=<optimized out>, expected=0, futex_word=0x7fa635ed1488 <runtime_init_cond+40>) at ../sysdeps/unix/sysv/linux/futex-internal.h:88
88	../sysdeps/unix/sysv/linux/futex-internal.h: Nie ma takiego pliku ani katalogu.

Thread 2 (Thread 0x7fa6355c2700 (LWP 7421)):
#0  0x00007fa6355d1072 in futex_wait_cancelable (private=<optimized out>, expected=0, futex_word=0x7fa635ed1488 <runtime_init_cond+40>) at ../sysdeps/unix/sysv/linux/futex-internal.h:88
#1  __pthread_cond_wait_common (abstime=0x0, mutex=0x7fa635ed1420 <runtime_init_mu>, cond=0x7fa635ed1460 <runtime_init_cond>) at pthread_cond_wait.c:502
#2  __pthread_cond_wait (cond=0x7fa635ed1460 <runtime_init_cond>, mutex=0x7fa635ed1420 <runtime_init_mu>) at pthread_cond_wait.c:655
#3  0x00007fa635c4a423 in _cgo_wait_runtime_init_done () at gcc_libinit.c:40
#4  0x00007fa635c4a2ae in free (p0=0x0) at _cgo_export.c:19
#5  0x00007fa6355cc26d in __pthread_attr_destroy (attr=<optimized out>) at pthread_attr_destroy.c:40
#6  0x00007fa635c4a690 in x_cgo_init (g=0x7fa635eb55c0 <runtime.g0>, setg=<optimized out>) at gcc_linux_amd64.c:49
#7  0x00007fa635c41407 in runtime.rt0_go () at /usr/local/go/src/runtime/asm_amd64.s:199
#8  0x00007fa6355c2700 in ?? ()
#9  0x0000000000000000 in ?? ()

Thread 1 (Thread 0x7fa6360be740 (LWP 7420)):
#0  0x00007fa6355d1072 in futex_wait_cancelable (private=<optimized out>, expected=0, futex_word=0x7fa635ed1488 <runtime_init_cond+40>) at ../sysdeps/unix/sysv/linux/futex-internal.h:88
#1  __pthread_cond_wait_common (abstime=0x0, mutex=0x7fa635ed1420 <runtime_init_mu>, cond=0x7fa635ed1460 <runtime_init_cond>) at pthread_cond_wait.c:502
#2  __pthread_cond_wait (cond=0x7fa635ed1460 <runtime_init_cond>, mutex=0x7fa635ed1420 <runtime_init_mu>) at pthread_cond_wait.c:655
#3  0x00007fa635c4a423 in _cgo_wait_runtime_init_done () at gcc_libinit.c:40
#4  0x00007fa635c4a2ae in free (p0=p0@entry=0x5615ac7d7390) at _cgo_export.c:19
#5  0x00007fa63580fb4f in _nl_load_locale_from_archive (category=category@entry=12, namep=namep@entry=0x7ffde9675240) at loadarchive.c:190
#6  0x00007fa63580e6c7 in _nl_find_locale (locale_path=0x0, locale_path_len=0, category=category@entry=12, name=name@entry=0x7ffde9675240) at findlocale.c:154
#7  0x00007fa63580ddfc in __GI_setlocale (category=<optimized out>, locale=<optimized out>) at setlocale.c:340
#8  0x00005615ac2e085d in ?? ()
#9  0x00007fa6358031c1 in __libc_start_main (main=0x5615ac2e0830, argc=1, argv=0x7ffde9675428, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7ffde9675418) at ../csu/libc-start.c:308
#10 0x00005615ac2e0aba in ?? ()

This works fine with equivalent C version:

$ cat main.c 
void free(void* p)
{
}
$ g++ main.c -fPIC -shared -ldl -o fake_malloc.so
$ LD_PRELOAD=./fake_malloc.so yes
y
y
...

It looks like some sort of deadlock in _cgo_wait_runtime_init_done

What did you expect to see?

Stream of 'y'.

What did you see instead?

Nothing.

Metadata

Metadata

Assignees

No one assigned

    Labels

    NeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.compiler/runtimeIssues related to the Go compiler and/or runtime.help wanted

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions