v icon indicating copy to clipboard operation
v copied to clipboard

net: net.listen_tcp fail in -prod mode

Open kbkpbot opened this issue 1 year ago • 3 comments

Describe the bug

when compile a simple net app, it will fail in prod mode

Reproduction Steps

test.v

module main
import net

fn main() {
	net.listen_tcp(.ip6, ':8081') or {
		ecode := err.code()
		panic('failed to listen ${ecode} ${err}')
	}
       println('hello world')
}

Compile in prod mode

v test.v -prod

Then run ./test

Expected Behavior

should run without panic

hello world

Current Behavior

V panic: failed to listen 0 net: socket error: 88; code: 88; binding to :8081 failed v hash: 298a2a2 | 0x7f3953c29d90 | /lib/x86_64-linux-gnu/libc.so.6(+0x29d90) | 0x7f3953c29e40 | /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0x80) | 0x560c9ac42745 | ./test(+0x3745)

Possible Solution

compile with tcc, will OK

v test.v

Additional Information/Context

No response

V version

V 0.4.4 298a2a2

Environment details (OS name and version, etc.)

V full version: V 0.4.4 349741d.298a2a2 OS: linux, Ubuntu 22.04.4 LTS Processor: 8 cpus, 64bit, little endian, Intel(R) Core(TM) i7-9700 CPU @ 3.00GHz

getwd: /home/mars/v/wrk vexe: /HD/github/kbkpbot/v/v vexe mtime: 2024-02-17 11:53:11

vroot: OK, value: /HD/github/kbkpbot/v VMODULES: OK, value: /home/mars/.vmodules VTMP: OK, value: /tmp/v_1000

Git version: git version 2.34.1 Git vroot status: weekly.2024.06-92-g298a2a2d .git/config present: true

CC version: cc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0 thirdparty/tcc status: thirdparty-linux-amd64 99683af0

[!NOTE] You can use the 👍 reaction to increase the issue's priority for developers.

Please note that only the 👍 reaction to the issue itself counts as a vote. Other reactions and those to comments will not be taken into account.

kbkpbot avatar Feb 17 '24 12:02 kbkpbot

change

net.listen_tcp(.ip6, ':8081') 

to

net.listen_tcp(.ip, ':8081') 

The same panic.

kbkpbot avatar Feb 17 '24 12:02 kbkpbot

If comment out s.set_dualstack(options.dualstack) or {} in vlib/net/tcp.c.v pub fn listen_tcp, then has no this bug.

kbkpbot avatar Feb 17 '24 13:02 kbkpbot

v test.v -cc clang -prod this is ok (Ubuntu clang version 14.0.0-1ubuntu1.1) v test.v -cc gcc -prod this will panic(gcc version 11.4.0 (Ubuntu 11.4.0-1ubuntu1~22.04)) .

kbkpbot avatar Feb 17 '24 14:02 kbkpbot

gcc -fwrapv -O2 -flto -DNDEBUG "/home/mars/.vmodules/cache/76/769009b5e03b3475e2b1f9c2b837a8b2.module.builtin.o" -o "/home/mars/v/wrk/test" -D GC_BUILTIN_ATOMIC=1 -D GC_THREADS=1 -I "/HD/github/kbkpbot/v/thirdparty/libgc/include" "/tmp/v_1000/test.tmp.c" -std=gnu99 -D_DEFAULT_SOURCE -ldl -lpthread

compile will show warning, and the test is OK

lto-wrapper: warning: using serial compilation of 3 LTRANS jobs

But if compile with -O3, compile will show warnings , and the test if panic

gcc -fwrapv -O3 -flto -DNDEBUG "/home/mars/.vmodules/cache/76/769009b5e03b3475e2b1f9c2b837a8b2.module.builtin.o" -o "/home/mars/v/wrk/test" -D GC_BUILTIN_ATOMIC=1 -D GC_THREADS=1 -I "/HD/github/kbkpbot/v/thirdparty/libgc/include" "/tmp/v_1000/test.tmp.c" -std=gnu99 -D_DEFAULT_SOURCE -ldl -lpthread
lto-wrapper: warning: using serial compilation of 3 LTRANS jobs
In function ‘memcpy’,
    inlined from ‘vmemcpy’ at /tmp/v_1000/test.tmp.c:10128:10,
    inlined from ‘string_clone’ at /tmp/v_1000/test.tmp.c:12341:3,
    inlined from ‘string_trim’ at /tmp/v_1000/test.tmp.c:13617:10,
    inlined from ‘string_trim_space’ at /tmp/v_1000/test.tmp.c:13612:9,
    inlined from ‘print_backtrace_skipping_top_frames_linux.isra’ at /tmp/v_1000/test.tmp.c:9323:15:
/usr/include/x86_64-linux-gnu/bits/string_fortified.h:29:10: warning: ‘__builtin_memcpy’ specified bound between 18446744071562067968 and 18446744073709551615 exceeds maximum object size 9223372036854775807 [-Wstringop-overflow=]
   29 |   return __builtin___memcpy_chk (__dest, __src, __len,
      |          ^
In function ‘memcpy’,
    inlined from ‘vmemcpy’ at /tmp/v_1000/test.tmp.c:10128:10,
    inlined from ‘string_clone’ at /tmp/v_1000/test.tmp.c:12341:3,
    inlined from ‘string_all_before’ at /tmp/v_1000/test.tmp.c:13989:10,
    inlined from ‘print_backtrace_skipping_top_frames_linux.isra’ at /tmp/v_1000/test.tmp.c:9305:26:
/usr/include/x86_64-linux-gnu/bits/string_fortified.h:29:10: warning: ‘__builtin_memcpy’ specified bound between 18446744071562067968 and 18446744073709551615 exceeds maximum object size 9223372036854775807 [-Wstringop-overflow=]
   29 |   return __builtin___memcpy_chk (__dest, __src, __len,
      |          ^

Search found that a open issue has same problem: #18738

kbkpbot avatar Feb 18 '24 02:02 kbkpbot

For me, it fails with gcc, but succeeds with clang.

JalonSolov avatar Feb 18 '24 02:02 JalonSolov

It's only on linux for me, have no issues on windows

Casper64 avatar Feb 18 '24 11:02 Casper64

After some tests, I found that in -prod mode, after s := new_tcp_socket() in fn listen_tcp(), s.handle will become ZERO. This will cause following operations on socket s fail.

Not sure what cause this bug. Maybe gcc -O3 -flto flag? (compile without -flto or just -O2 -flto will remove this bug)

https://github.com/vlang/v/blob/fa7af809fcd36b20d7609df98bcf835e02a11521/vlib/net/tcp.c.v#L334

pub fn listen_tcp(family AddrFamily, saddr string, options ListenOptions) !&TcpListener {
	if family != .ip && family != .ip6 {
		return error('listen_tcp only supports ip and ip6')
	}
	mut s := new_tcp_socket(family) or { return error('${err.msg()}; could not create new socket') }

// -prod mode, will make s.handle = 0 here, this is not correct!

	s.set_dualstack(options.dualstack) or {}

	addrs := resolve_addrs(saddr, family, .tcp) or {
		return error('${err.msg()}; could not resolve address ${saddr}')
	}

kbkpbot avatar Feb 19 '24 00:02 kbkpbot

By disassemble the ./test file, it shows that gcc -O3 -flto generate wrong instruction sequence. At 0000564A60BA76FC , it read handle into ebx (which is ZERO), then use rep movsd update the handle to its correct value.

.text:0000564A60BA76E0 loc_564A60BA76E0:                       ; CODE XREF: main__main+8FC↓j
.text:0000564A60BA76E0                 movdqa  xmm7, cs:_const_none__
.text:0000564A60BA76E8                 mov     eax, dword ptr [rsp+578h+src]
.text:0000564A60BA76EC                 mov     byte ptr [rsp+578h+var_338], 0
.text:0000564A60BA76F4                 lea     rdi, [rsp+578h+var_4C8]
.text:0000564A60BA76FC                 mov     ebx, [rsp+578h+fd] ; <================Read `handle`
.text:0000564A60BA7703                 mov     ecx, 0Ch
.text:0000564A60BA7708                 mov     rsi, rbp
.text:0000564A60BA770B                 movups  [rsp+578h+var_330], xmm7
.text:0000564A60BA7713                 movdqa  xmm7, cs:xmmword_564A60BF8910
.text:0000564A60BA771B                 mov     dword ptr [rsp+578h+var_310], eax
.text:0000564A60BA7722                 rep movsd               ; <==============Update `handle`
.text:0000564A60BA7724                 xor     esi, esi
.text:0000564A60BA7726                 mov     edi, ebx        ; <=================Use `handle`
.text:0000564A60BA7728                 movups  [rsp+578h+var_320], xmm7
.text:0000564A60BA7730                 call    indent_net__TcpSocket_str
.text:0000564A60BA7735                 mov     rdi, rax        ; ptr
.text:0000564A60BA7738                 mov     esi, edx
.text:0000564A60BA773A                 test    rax, rax
.text:0000564A60BA773D                 jz      loc_564A60BA7E90
.text:0000564A60BA7743                 call    _writeln_to_fd_constprop_0_isra_0

kbkpbot avatar Feb 19 '24 10:02 kbkpbot