axboe / liburing

Library providing helpers for the Linux kernel io_uring support
MIT License
2.77k stars 398 forks source link

`io_uring_prep_recv` does not return `0`? #1183

Closed YoSTEALTH closed 1 month ago

YoSTEALTH commented 1 month ago

While using recv in C, you get -1 on error, 0 on EOF and >0 on success.

In python its >0 on success 0 on EOF and OSError

In io_uring_prep_recv I am not getting 0 on EOF but just hangs till connection times out. Tried with SOCK_NONBLOCK as well.

# tracer: nop
#
# entries-in-buffer/entries-written: 29/29   #P:24
#
#                                _-----=> irqs-off/BH-disabled
#                               / _----=> need-resched
#                              | / _---=> hardirq/softirq
#                              || / _--=> preempt-depth
#                              ||| / _-=> migrate-disable
#                              |||| /     delay
#           TASK-PID     CPU#  |||||  TIMESTAMP  FUNCTION
#              | |         |   |||||     |         |
         python3-19736   [023] ..... 11565.405789: io_uring_create: ring 00000000989f94e6, fd 3 sq size 1024, cq size 2048, flags 0x10000
         python3-19736   [023] ..... 11565.405840: io_uring_submit_req: ring 00000000989f94e6, req 000000009ea0dd92, user_data 0x7edc84df4ee0, opcode NOP, flags 0x0, sq_thread 0
         python3-19736   [023] ...1. 11565.405842: io_uring_complete: ring 00000000989f94e6, req 000000009ea0dd92, user_data 0x7edc84df4ee0, result 0, cflags 0x0 extra1 0 extra2 0
         python3-19736   [023] ..... 11565.405857: io_uring_submit_req: ring 00000000989f94e6, req 000000009ea0dd92, user_data 0x7edc84ca2fe0, opcode SOCKET, flags 0x0, sq_thread 0
         python3-19736   [023] ...1. 11565.405868: io_uring_complete: ring 00000000989f94e6, req 000000009ea0dd92, user_data 0x7edc84ca2fe0, result 4, cflags 0x0 extra1 0 extra2 0
         python3-19736   [023] ..... 11565.433310: io_uring_submit_req: ring 00000000989f94e6, req 000000009ea0dd92, user_data 0x7edc84df4ee0, opcode CONNECT, flags 0x0, sq_thread 0
         python3-19736   [023] ..... 11565.433311: io_uring_file_get: ring 00000000989f94e6, req 000000009ea0dd92, user_data 0x7edc84df4ee0, fd 4
         python3-19736   [023] ..... 11565.433340: io_uring_poll_arm: ring 00000000989f94e6, req 000000009ea0dd92, user_data 0x7edc84df4ee0, opcode CONNECT, mask 0xc000010e, events 0xc000213e
         python3-19736   [023] ..... 11565.433343: io_uring_cqring_wait: ring 00000000989f94e6, min_events 1
          <idle>-0       [015] d.s3. 11565.456801: io_uring_task_add: ring 00000000989f94e6, req 000000009ea0dd92, user_data 0x7edc84df4ee0, opcode CONNECT, mask 0
         python3-19736   [023] ...1. 11565.456879: io_uring_complete: ring 00000000989f94e6, req 000000009ea0dd92, user_data 0x7edc84df4ee0, result 0, cflags 0x0 extra1 0 extra2 0
         python3-19736   [023] ..... 11565.456882: io_uring_task_work_run: tctx 00000000771d8d11, count 1, loops 1
         python3-19736   [023] ..... 11565.456937: io_uring_submit_req: ring 00000000989f94e6, req 000000009ea0dd92, user_data 0x7edc84ca2fe0, opcode SEND, flags 0x0, sq_thread 0
         python3-19736   [023] ..... 11565.456938: io_uring_file_get: ring 00000000989f94e6, req 000000009ea0dd92, user_data 0x7edc84ca2fe0, fd 4
         python3-19736   [023] ...1. 11565.456967: io_uring_complete: ring 00000000989f94e6, req 000000009ea0dd92, user_data 0x7edc84ca2fe0, result 54, cflags 0x0 extra1 0 extra2 0
         python3-19736   [023] ..... 11565.457015: io_uring_submit_req: ring 00000000989f94e6, req 000000009ea0dd92, user_data 0x7edc84df4ee0, opcode RECV, flags 0x0, sq_thread 0
         python3-19736   [023] ..... 11565.457015: io_uring_file_get: ring 00000000989f94e6, req 000000009ea0dd92, user_data 0x7edc84df4ee0, fd 4
         python3-19736   [023] ..... 11565.457018: io_uring_poll_arm: ring 00000000989f94e6, req 000000009ea0dd92, user_data 0x7edc84df4ee0, opcode RECV, mask 0xc000004b, events 0xc000207b
         python3-19736   [023] ..... 11565.457019: io_uring_cqring_wait: ring 00000000989f94e6, min_events 1
          <idle>-0       [015] dNs3. 11565.482176: io_uring_task_add: ring 00000000989f94e6, req 000000009ea0dd92, user_data 0x7edc84df4ee0, opcode RECV, mask c3
         python3-19736   [023] ...1. 11565.482261: io_uring_complete: ring 00000000989f94e6, req 000000009ea0dd92, user_data 0x7edc84df4ee0, result 1024, cflags 0x4 extra1 0 extra2 0
         python3-19736   [023] ..... 11565.482265: io_uring_task_work_run: tctx 00000000771d8d11, count 1, loops 1
         python3-19736   [023] ..... 11565.482427: io_uring_submit_req: ring 00000000989f94e6, req 000000009ea0dd92, user_data 0x7edc84ca2fe0, opcode RECV, flags 0x0, sq_thread 0
         python3-19736   [023] ..... 11565.482428: io_uring_file_get: ring 00000000989f94e6, req 000000009ea0dd92, user_data 0x7edc84ca2fe0, fd 4
         python3-19736   [023] ...1. 11565.482433: io_uring_complete: ring 00000000989f94e6, req 000000009ea0dd92, user_data 0x7edc84ca2fe0, result 569, cflags 0x0 extra1 0 extra2 0
         python3-19736   [023] ..... 11565.482473: io_uring_submit_req: ring 00000000989f94e6, req 000000009ea0dd92, user_data 0x7edc84df4ee0, opcode RECV, flags 0x0, sq_thread 0
         python3-19736   [023] ..... 11565.482473: io_uring_file_get: ring 00000000989f94e6, req 000000009ea0dd92, user_data 0x7edc84df4ee0, fd 4
         python3-19736   [023] ..... 11565.482477: io_uring_poll_arm: ring 00000000989f94e6, req 000000009ea0dd92, user_data 0x7edc84df4ee0, opcode RECV, mask 0xc000004b, events 0xc000207b
         python3-19736   [023] ..... 11565.482479: io_uring_cqring_wait: ring 00000000989f94e6, min_events 1

having to kill the process:

python3-19736   [023] ...1. 11589.267159: io_uring_task_add: ring 00000000989f94e6, req 000000009ea0dd92, user_data 0x7edc84df4ee0, opcode RECV, mask 0
kworker/23:2-482     [023] ...1. 11589.267236: io_uring_complete: ring 00000000989f94e6, req 000000009ea0dd92, user_data 0x7edc84df4ee0, result -125, cflags 0x0 extra1 0 extra2 0
YoSTEALTH commented 1 month ago

This code works and return data as it should:

from shakti import run, socket, connect, recv, send, shutdown, close

async def client(host, port, header):
    received = bytearray()
    client_fd = await socket()
    await connect(client_fd, host, port)
    print('client sent:', await send(client_fd, header))
    while data := await recv(client_fd, 1024):
        received.extend(data)
    print('client recv:', received)
    await close(client_fd)
    print('closed')

if __name__ == '__main__':
    host = 'example.com'
    port = 80
    header = f'GET / HTTP/1.0\nHost: {host}\nUser-Agent: Testing\n\n'.encode()
    run(client(host, port, header))

# client sent: 54
# result: 1024
# result: 424
# result: 169
# result: 0
# client recv: bytearray(b'HTTP/1.0 200 OK ...')
# closed

changing the code to HTTP/1.1 does not return 0 and hangs!

header = f'GET / HTTP/1.1\nHost: {host}\nUser-Agent: Testing\n\n'.encode()
YoSTEALTH commented 1 month ago

Not a bug, was having a brain fart not using Connection: close for HTTP/1.1