Cgo with net/http seg faults at runtime on MacOS

Using go 1.21.1 and am attempting to wrap a native library with cgo, see GenomicsDB-Go the native library has external dependencies on curl/openssl/zlib. The bindings build and test fine on both Linux and MacOS platforms, but when net/http and github.com/GenomicsDB/GenomicsDB-Go/bindings are imported together, it segfaults only on MacOS when invoking system call connect(). The native library does have dependencies on the OSX Framework for system calls, somehow this is clashing with the Go runtime. Any suggestions on what can be done here? Thanks!

1 Like
SIGSEGV: segmentation violation
PC=0x196d9e674 m=4 sigcode=2

goroutine 0 [idle]:
syscall.syscall(0x14000064838?, 0x1005f74d4?, 0x20?, 0x14000080000?)
	/usr/local/go/src/runtime/sys_darwin.go:23 +0x58 fp=0x140000647d0 sp=0x14000064740 pc=0x1004e5808
syscall.connect(0x6873fdac?, 0x0?, 0x0?)
	/usr/local/go/src/syscall/zsyscall_darwin_arm64.go:87 +0x38 fp=0x14000064810 sp=0x140000647d0 pc=0x10052bc58
syscall.Connect(0x50?, {0x1008a9bc8?, 0x140000a0000?})
	/usr/local/go/src/syscall/syscall_unix.go:298 +0x58 fp=0x14000064840 sp=0x14000064810 pc=0x10052acb8
net.(*netFD).connect(0x1400009e000, {0x1008abfe0?, 0x14000090000}, {0x100e145e0?, 0x14000064a78?}, {0x1008a9bc8?, 0x140000a0000?})
	/usr/local/go/src/net/fd_unix.go:59 +0x60 fp=0x140000649e0 sp=0x14000064840 pc=0x1005ee840
net.(*netFD).dial(0x1400009e000, {0x1008abfe0, 0x14000090000}, {0x1008ad078?, 0x0?}, {0x1008ad078?, 0x14000115050}, 0x14000064b80?)
	/usr/local/go/src/net/sock_posix.go:151 +0x304 fp=0x14000064ab0 sp=0x140000649e0 pc=0x1005fde24
net.socket({0x1008abfe0, 0x14000090000}, {0x100760e7e, 0x3}, 0x2, 0x1, 0x1007610eb?, 0xb?, {0x1008ad078?, 0x0}, ...)
	/usr/local/go/src/net/sock_posix.go:70 +0x21c fp=0x14000064b70 sp=0x14000064ab0 pc=0x1005fda1c
net.internetSocket({0x1008abfe0, 0x14000090000}, {0x100760e7e, 0x3}, {0x1008ad078, 0x0}, {0x1008ad078, 0x14000115050}, 0x10001019b98f8?, 0x1004d5ed0?, ...)
	/usr/local/go/src/net/ipsock_posix.go:142 +0xa8 fp=0x14000064c00 sp=0x14000064b70 pc=0x1005f6de8
net.(*sysDialer).doDialTCPProto(0x14000118b40, {0x1008abfe0, 0x14000090000}, 0x0, 0x100af69c0?, 0x14000080000?)
	/usr/local/go/src/net/tcpsock_posix.go:78 +0xb0 fp=0x14000064cc0 sp=0x14000064c00 pc=0x100600d80
net.(*sysDialer).doDialTCP(...)
	/usr/local/go/src/net/tcpsock_posix.go:68
net.(*sysDialer).dialTCP(0x14000064d38?, {0x1008abfe0?, 0x14000090000?}, 0x100890600?, 0x14000064d01?)
	/usr/local/go/src/net/tcpsock_posix.go:64 +0x70 fp=0x14000064d00 sp=0x14000064cc0 pc=0x100600c50
net.(*sysDialer).dialSingle(0x14000118b40, {0x1008abfe0, 0x14000090000}, {0x1008ab278?, 0x14000115050})
	/usr/local/go/src/net/dial.go:649 +0x1cc fp=0x14000064de0 sp=0x14000064d00 pc=0x1005e74ec
net.(*sysDialer).dialSerial(0x14000118b40, {0x1008abf70, 0x1400010a230}, {0x14000160180?, 0x6, 0x0?})
	/usr/local/go/src/net/dial.go:614 +0x1a0 fp=0x14000064ef0 sp=0x14000064de0 pc=0x1005e6f40
net.(*sysDialer).dialParallel.func1({0x1008abf70?, 0x1400010a230?}, 0x1)
	/usr/local/go/src/net/dial.go:534 +0x7c fp=0x14000064fa0 sp=0x14000064ef0 pc=0x1005e6c8c
net.(*sysDialer).dialParallel.func3()
	/usr/local/go/src/net/dial.go:549 +0x3c fp=0x14000064fd0 sp=0x14000064fa0 pc=0x1005e6bdc
runtime.goexit()
	/usr/local/go/src/runtime/asm_arm64.s:1197 +0x4 fp=0x14000064fd0 sp=0x14000064fd0 pc=0x1004e9024
created by net.(*sysDialer).dialParallel in goroutine 6
	/usr/local/go/src/net/dial.go:549 +0x21c

goroutine 9 [syscall]:
syscall.syscall(0x14000064838?, 0x1005f74d4?, 0x20?, 0x14000080000?)
	/usr/local/go/src/runtime/sys_darwin.go:23 +0x58 fp=0x140000647d0 sp=0x14000064740 pc=0x1004e5808
syscall.connect(0x6873fdac?, 0x0?, 0x0?)
	/usr/local/go/src/syscall/zsyscall_darwin_arm64.go:87 +0x38 fp=0x14000064810 sp=0x140000647d0 pc=0x10052bc58
syscall.Connect(0x50?, {0x1008a9bc8?, 0x140000a0000?})
	/usr/local/go/src/syscall/syscall_unix.go:298 +0x58 fp=0x14000064840 sp=0x14000064810 pc=0x10052acb8
net.(*netFD).connect(0x1400009e000, {0x1008abfe0?, 0x14000090000}, {0x100e145e0?, 0x14000064a78?}, {0x1008a9bc8?, 0x140000a0000?})
	/usr/local/go/src/net/fd_unix.go:59 +0x60 fp=0x140000649e0 sp=0x14000064840 pc=0x1005ee840
net.(*netFD).dial(0x1400009e000, {0x1008abfe0, 0x14000090000}, {0x1008ad078?, 0x0?}, {0x1008ad078?, 0x14000115050}, 0x14000064b80?)
	/usr/local/go/src/net/sock_posix.go:151 +0x304 fp=0x14000064ab0 sp=0x140000649e0 pc=0x1005fde24
net.socket({0x1008abfe0, 0x14000090000}, {0x100760e7e, 0x3}, 0x2, 0x1, 0x1007610eb?, 0xb?, {0x1008ad078?, 0x0}, ...)
	/usr/local/go/src/net/sock_posix.go:70 +0x21c fp=0x14000064b70 sp=0x14000064ab0 pc=0x1005fda1c
net.internetSocket({0x1008abfe0, 0x14000090000}, {0x100760e7e, 0x3}, {0x1008ad078, 0x0}, {0x1008ad078, 0x14000115050}, 0x10001019b98f8?, 0x1004d5ed0?, ...)
	/usr/local/go/src/net/ipsock_posix.go:142 +0xa8 fp=0x14000064c00 sp=0x14000064b70 pc=0x1005f6de8
net.(*sysDialer).doDialTCPProto(0x14000118b40, {0x1008abfe0, 0x14000090000}, 0x0, 0x100af69c0?, 0x14000080000?)
	/usr/local/go/src/net/tcpsock_posix.go:78 +0xb0 fp=0x14000064cc0 sp=0x14000064c00 pc=0x100600d80
net.(*sysDialer).doDialTCP(...)
	/usr/local/go/src/net/tcpsock_posix.go:68
net.(*sysDialer).dialTCP(0x14000064d38?, {0x1008abfe0?, 0x14000090000?}, 0x100890600?, 0x14000064d01?)
	/usr/local/go/src/net/tcpsock_posix.go:64 +0x70 fp=0x14000064d00 sp=0x14000064cc0 pc=0x100600c50
net.(*sysDialer).dialSingle(0x14000118b40, {0x1008abfe0, 0x14000090000}, {0x1008ab278?, 0x14000115050})
	/usr/local/go/src/net/dial.go:649 +0x1cc fp=0x14000064de0 sp=0x14000064d00 pc=0x1005e74ec
net.(*sysDialer).dialSerial(0x14000118b40, {0x1008abf70, 0x1400010a230}, {0x14000160180?, 0x6, 0x0?})
	/usr/local/go/src/net/dial.go:614 +0x1a0 fp=0x14000064ef0 sp=0x14000064de0 pc=0x1005e6f40
net.(*sysDialer).dialParallel.func1({0x1008abf70?, 0x1400010a230?}, 0x1)
	/usr/local/go/src/net/dial.go:534 +0x7c fp=0x14000064fa0 sp=0x14000064ef0 pc=0x1005e6c8c
net.(*sysDialer).dialParallel.func3()
	/usr/local/go/src/net/dial.go:549 +0x3c fp=0x14000064fd0 sp=0x14000064fa0 pc=0x1005e6bdc
runtime.goexit()
	/usr/local/go/src/runtime/asm_arm64.s:1197 +0x4 fp=0x14000064fd0 sp=0x14000064fd0 pc=0x1004e9024
created by net.(*sysDialer).dialParallel in goroutine 6
	/usr/local/go/src/net/dial.go:549 +0x21c

goroutine 1 [select]:
runtime.gopark(0x140001496f0?, 0x4?, 0xb0?, 0x1a?, 0x14000149598?)
	/usr/local/go/src/runtime/proc.go:398 +0xc8 fp=0x14000149410 sp=0x140001493f0 pc=0x1004b8df8
runtime.selectgo(0x140001496f0, 0x14000149590, 0x14000020280?, 0x0, 0x100b36840?, 0x1)
	/usr/local/go/src/runtime/select.go:327 +0x608 fp=0x14000149520 sp=0x14000149410 pc=0x1004c9548
net/http.(*Transport).getConn(0x100afa620, 0x14000100500, {{}, 0x0, {0x10076b5f2, 0x4}, {0x14000026168, 0x11}, 0x0})
	/usr/local/go/src/net/http/transport.go:1393 +0x448 fp=0x14000149740 sp=0x14000149520 pc=0x1006b82b8
net/http.(*Transport).roundTrip(0x100afa620, 0x1400015e000)
	/usr/local/go/src/net/http/transport.go:591 +0x658 fp=0x14000149970 sp=0x14000149740 pc=0x1006b4638
net/http.(*Transport).RoundTrip(0x14000149a58?, 0x1008a95c8?)
	/usr/local/go/src/net/http/roundtrip.go:17 +0x1c fp=0x14000149990 sp=0x14000149970 pc=0x1006abbcc
net/http.send(0x1400015e000, {0x1008a95c8, 0x100afa620}, {0x1006860b0?, 0x8?, 0x0?})
	/usr/local/go/src/net/http/client.go:260 +0x4e0 fp=0x14000149bc0 sp=0x14000149990 pc=0x100684960
net/http.(*Client).send(0x100b004a0, 0x1400015e000, {0x100e21828?, 0x14000149c88?, 0x0?})
	/usr/local/go/src/net/http/client.go:181 +0x9c fp=0x14000149c40 sp=0x14000149bc0 pc=0x10068431c
net/http.(*Client).do(0x100b004a0, 0x1400015e000)
	/usr/local/go/src/net/http/client.go:724 +0x6f4 fp=0x14000149e50 sp=0x14000149c40 pc=0x100686104
net/http.(*Client).Do(...)
	/usr/local/go/src/net/http/client.go:590
net/http.(*Client).Get(0x140000021a0?, {0x10076b5f2?, 0x14000149f28?})
	/usr/local/go/src/net/http/client.go:488 +0x74 fp=0x14000149eb0 sp=0x14000149e50 pc=0x100685904
net/http.Get(...)
	/usr/local/go/src/net/http/client.go:457
main.main()
	/Users/nalini/GenomicsDB-Go/example-genomicsdb-go/main.go:11 +0x34 fp=0x14000149f30 sp=0x14000149eb0 pc=0x10075fa44
runtime.main()
	/usr/local/go/src/runtime/proc.go:267 +0x2bc fp=0x14000149fd0 sp=0x14000149f30 pc=0x1004b89cc
runtime.goexit()
	/usr/local/go/src/runtime/asm_arm64.s:1197 +0x4 fp=0x14000149fd0 sp=0x14000149fd0 pc=0x1004e9024

goroutine 2 [force gc (idle)]:
runtime.gopark(0x0?, 0x0?, 0x0?, 0x0?, 0x0?)
	/usr/local/go/src/runtime/proc.go:398 +0xc8 fp=0x14000054f90 sp=0x14000054f70 pc=0x1004b8df8
runtime.goparkunlock(...)
	/usr/local/go/src/runtime/proc.go:404
runtime.forcegchelper()
	/usr/local/go/src/runtime/proc.go:322 +0xb8 fp=0x14000054fd0 sp=0x14000054f90 pc=0x1004b8c88
runtime.goexit()
	/usr/local/go/src/runtime/asm_arm64.s:1197 +0x4 fp=0x14000054fd0 sp=0x14000054fd0 pc=0x1004e9024
created by runtime.init.6 in goroutine 1
	/usr/local/go/src/runtime/proc.go:310 +0x24

goroutine 3 [GC sweep wait]:
runtime.gopark(0x0?, 0x0?, 0x0?, 0x0?, 0x0?)
	/usr/local/go/src/runtime/proc.go:398 +0xc8 fp=0x14000055760 sp=0x14000055740 pc=0x1004b8df8
runtime.goparkunlock(...)
	/usr/local/go/src/runtime/proc.go:404
runtime.bgsweep(0x0?)
	/usr/local/go/src/runtime/mgcsweep.go:280 +0xa0 fp=0x140000557b0 sp=0x14000055760 pc=0x1004a5a10
runtime.gcenable.func1()
	/usr/local/go/src/runtime/mgc.go:200 +0x28 fp=0x140000557d0 sp=0x140000557b0 pc=0x10049a4e8
runtime.goexit()
	/usr/local/go/src/runtime/asm_arm64.s:1197 +0x4 fp=0x140000557d0 sp=0x140000557d0 pc=0x1004e9024
created by runtime.gcenable in goroutine 1
	/usr/local/go/src/runtime/mgc.go:200 +0x6c

goroutine 4 [GC scavenge wait]:
runtime.gopark(0x1400007e000?, 0x1007f1928?, 0x1?, 0x0?, 0x140000031e0?)
	/usr/local/go/src/runtime/proc.go:398 +0xc8 fp=0x14000055f50 sp=0x14000055f30 pc=0x1004b8df8
runtime.goparkunlock(...)
	/usr/local/go/src/runtime/proc.go:404
runtime.(*scavengerState).park(0x100b00900)
	/usr/local/go/src/runtime/mgcscavenge.go:425 +0x5c fp=0x14000055f80 sp=0x14000055f50 pc=0x1004a328c
runtime.bgscavenge(0x0?)
	/usr/local/go/src/runtime/mgcscavenge.go:653 +0x44 fp=0x14000055fb0 sp=0x14000055f80 pc=0x1004a37e4
runtime.gcenable.func2()
	/usr/local/go/src/runtime/mgc.go:201 +0x28 fp=0x14000055fd0 sp=0x14000055fb0 pc=0x10049a488
runtime.goexit()
	/usr/local/go/src/runtime/asm_arm64.s:1197 +0x4 fp=0x14000055fd0 sp=0x14000055fd0 pc=0x1004e9024
created by runtime.gcenable in goroutine 1
	/usr/local/go/src/runtime/mgc.go:201 +0xac

goroutine 5 [finalizer wait]:
runtime.gopark(0x140000545a8?, 0x1004e43e4?, 0x1?, 0x45?, 0x100504094?)
	/usr/local/go/src/runtime/proc.go:398 +0xc8 fp=0x14000054580 sp=0x14000054560 pc=0x1004b8df8
runtime.runfinq()
	/usr/local/go/src/runtime/mfinal.go:193 +0x108 fp=0x140000547d0 sp=0x14000054580 pc=0x1004995d8
runtime.goexit()
	/usr/local/go/src/runtime/asm_arm64.s:1197 +0x4 fp=0x140000547d0 sp=0x140000547d0 pc=0x1004e9024
created by runtime.createfing in goroutine 1
	/usr/local/go/src/runtime/mfinal.go:163 +0x80

goroutine 6 [select]:
runtime.gopark(0x1400014b748?, 0x2?, 0xe8?, 0xb4?, 0x1400014b5f4?)
	/usr/local/go/src/runtime/proc.go:398 +0xc8 fp=0x1400014b4a0 sp=0x1400014b480 pc=0x1004b8df8
runtime.selectgo(0x1400014b748, 0x1400014b5f0, 0x1400014b688?, 0x0, 0x0?, 0x1)
	/usr/local/go/src/runtime/select.go:327 +0x608 fp=0x1400014b5b0 sp=0x1400014b4a0 pc=0x1004c9548
net.(*sysDialer).dialParallel(0x14000118b40, {0x1008abfe0, 0x140001320e0}, {0x14000160180, 0x6, 0x8}, {0x14000100640, 0x4, 0x4})
	/usr/local/go/src/net/dial.go:556 +0x354 fp=0x1400014b810 sp=0x1400014b5b0 pc=0x1005e6884
net.(*Dialer).DialContext(0x14000132070, {0x1008abe90, 0x100b357a0}, {0x100760e7e, 0x3}, {0x14000026168, 0x11})
	/usr/local/go/src/net/dial.go:506 +0x574 fp=0x1400014b950 sp=0x1400014b810 pc=0x1005e63b4
net.(*Dialer).DialContext-fm({0x1008abe90?, 0x100b357a0?}, {0x100760e7e?, 0x100b00fa0?}, {0x14000026168?, 0x0?})
	<autogenerated>:1 +0x54 fp=0x1400014b9a0 sp=0x1400014b950 pc=0x1006ca294
net/http.(*Transport).dial(0x14000069c08?, {0x1008abe90?, 0x100b357a0?}, {0x100760e7e?, 0x100acbda0?}, {0x14000026168?, 0x169?})
	/usr/local/go/src/net/http/transport.go:1183 +0xdc fp=0x1400014ba10 sp=0x1400014b9a0 pc=0x1006b772c
net/http.(*Transport).dialConn(0x100afa620, {0x1008abe90, 0x100b357a0}, {{}, 0x0, {0x10076b5f2, 0x4}, {0x14000026168, 0x11}, 0x0})
	/usr/local/go/src/net/http/transport.go:1625 +0x61c fp=0x1400014bec0 sp=0x1400014ba10 pc=0x1006b9e8c
net/http.(*Transport).dialConnFor(0x0?, 0x1400012a2c0)
	/usr/local/go/src/net/http/transport.go:1467 +0x7c fp=0x1400014bfb0 sp=0x1400014bec0 pc=0x1006b8cec
net/http.(*Transport).queueForDial.func1()
	/usr/local/go/src/net/http/transport.go:1436 +0x2c fp=0x1400014bfd0 sp=0x1400014bfb0 pc=0x1006b8c3c
runtime.goexit()
	/usr/local/go/src/runtime/asm_arm64.s:1197 +0x4 fp=0x1400014bfd0 sp=0x1400014bfd0 pc=0x1004e9024
created by net/http.(*Transport).queueForDial in goroutine 1
	/usr/local/go/src/net/http/transport.go:1436 +0x380

r0      0x14004000000
r1      0x8
r2      0x140000a000c
r3      0x14004000020
r4      0xfffffebffc000008
r5      0x3
r6      0x0
r7      0x0
r8      0x80000140000a0010
r9      0x2203
r10     0x18
r11     0x18
r12     0x100cfefd0
r13     0x0
r14     0x7fb
r15     0x8707980d
r16     0x196d9e640
r17     0x1f6917850
r18     0x0
r19     0x600001830300
r20     0x64fbd0c9
r21     0x140000a000c
r22     0x8
r23     0x14004000000
r24     0x140000a0010
r25     0x0
r26     0x1008a6af0
r27     0x830
r28     0x140000821a0
r29     0x1719a2ed0
lr      0x10075fd74
sp      0x1719a2e60
pc      0x196d9e674
fault   0x8
exit status 2
1 Like

first instinct is to check the binary of the GenomicsDB that it’s built for aarm64 as you’re on Apple Silicon. I couldn’t see in your install.sh in your repo whether you were setting arch params or not. Only checking os. Likewise in GenomicsDB’s CMakeLists I don’t see any arm checks/flags which makes me presume it’s amd64/x86. Build your Mac library with GOARCH=amd64 and see if it still segfaults. If not, you’ll have to build GenomicsDB with aarm64 arch for apple silicon to use it in go on apple silicon.

Thanks gabereiser I am building the native GenomicsDB library and the bindings on the same machine, not allowing for cross-compiling yet - macOS 13.x and arm64, all this seems to be in sync.

go env | grep ARCH
GOARCH='arm64'
GOHOSTARCH='arm64'

and

lipo -info /usr/local/lib/libtiledbgenomicsdb.dylib
Non-fat file: /usr/local/lib/libtiledbgenomicsdb.dylib is architecture: arm64

What is this code doing?

github.com/datma-health/federated-fiber/common/auth.getJSON

Whatever this function is doing, it’s making the http call, which is segfaulting, not sure it’s your library. I suggest setting some breakpoints in your code and walking through it starting at this function.

Actually, I had reproduced the issue with just this code. I have updated the entire segfault with callstack above.

package main

import (
	"log"
	"net/http"

	gdb "github.com/GenomicsDB/GenomicsDB-Go/bindings"
)

func main() {
	_, err1 := http.Get("http://www.google.com/robots.txt")
	if err1 != nil {
		log.Fatal(err1)
	}

	log.Println("Got GenomicsDB version: ", gdb.GetVersion())
}

Using your latest simplified code, it fails to compile due to missing genomicsdb in pkg-config. Usually go bindings will build the package using cgo. Fix it so that when I call go build and your bindings are built, that genomicsdb is built too. You’re halfway there, but I’m unable to debug or help further unless go bindings will compile.

Build Error: go build -o test -gcflags all=-N -l .
go build github.com/GenomicsDB/GenomicsDB-Go/bindings:
# pkg-config --cflags -- genomicsdb
Package genomicsdb was not found in the pkg-config search path.
Perhaps you should add the directory containing "genomicsdb.pc"
to the PKG_CONFIG_PATH environment variable
No package ‘genomicsdb’ found
pkg-config: exit status 1 (exit status 1)

genomicsdb is built as part of install-bindings, a separate step unfortunately. You can do go install github.com/GenomicsDB/GenomicsDB-Go/install-genomicsdb@latest and then invoke install-genomicsdb. This should install genomicsdb into /usr/local/lib and /usr/local/include with genomicsdb.pc in /usr/local/lib/pkgconfig and discoverable by cgo. You could add env PKG_CONFIG_PATH=/usr/local/lib/pkgconfig if needed.

What does removing the gdb import and fmt.Println and just making the http.Get result for you?

Commenting those parts out, the code runs fine!

~/GenomicsDB-Go/example-genomicsdb-go: !vi
vi main.go
~/GenomicsDB-Go/example-genomicsdb-go: go build
~/GenomicsDB-Go/example-genomicsdb-go: go run .
~/GenomicsDB-Go/example-genomicsdb-go: echo $?
0

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.