Skip to content

call sock_accept(or sock_recv) and close sock before next uv loop will cause entire program core dump #100

Closed
@chenfengyuan

Description

@chenfengyuan

Hi all,

call sock_accept and close sock before next uv loop will cause entire program core dump. Because epoll will return EBADF if libuv try register closed socket, then libuv will call abort. https://github.com/libuv/libuv/blob/7452ef4e06a4f99ee26b694c65476401534f2725/src/unix/linux-core.c#L225-L227

Run any code below directly can reproduce core dump. Core dump may cause programs hard to debug and make programmer take more time to find the root bug source.
If I don't use uvloop(comment asyncio.set_event_loop(uvloop.new_event_loop())), all code below will be fine.

sock_accept

# coding=utf-8
import uvloop
import asyncio
from signal import (
    signal,
    SIGINT,
)
import socket
from contextlib import (
    closing,
)
import logging
logging.basicConfig(format='%(asctime)s [%(process)d] [%(levelname)s] [%(filename)s:%(lineno)d] : %(message)s')


async def a():
    loop = asyncio.get_event_loop()
    sock = socket.socket()
    sock.bind(('127.0.0.1', 0))
    sock.listen(10)
    sock.setblocking(0)
    loop.sock_accept(sock)
    sock.close()

async def b():
    await asyncio.sleep(1)


def main():
    asyncio.set_event_loop(uvloop.new_event_loop())
    loop = asyncio.get_event_loop()
    loop.set_debug(True)
    signal(SIGINT, lambda s, f: loop.stop())
    loop.create_task(a())
    # noinspection PyBroadException
    try:
        loop.run_until_complete(loop.create_task(b()))
        # loop.run_forever()
    except:
        loop.stop()


if __name__ == '__main__':
    main()

sock_recv

# coding=utf-8
import uvloop
import asyncio
from signal import (
    signal,
    SIGINT,
)
import socket
from contextlib import (
    closing,
)
import logging
logging.basicConfig(format='%(asctime)s [%(process)d] [%(levelname)s] [%(filename)s:%(lineno)d] : %(message)s')


logger = logging.getLogger(__name__)


async def a():
    loop = asyncio.get_event_loop()
    sock = socket.socket()
    sock.connect(('github.com', 80))
    sock.setblocking(0)
    loop.sock_recv(sock, 10)
    sock.close()

async def b():
    await asyncio.sleep(1)


def main():
    asyncio.set_event_loop(uvloop.new_event_loop())
    loop = asyncio.get_event_loop()
    loop.set_debug(True)
    signal(SIGINT, lambda s, f: loop.stop())
    loop.create_task(a())
    # noinspection PyBroadException
    try:
        loop.run_until_complete(loop.create_task(b()))
        # loop.run_forever()
    except:
        loop.stop()


if __name__ == '__main__':
    main()

gdb backtrace

#0  __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:58
#1  0x00007ffff711937a in __GI_abort () at abort.c:89
#2  0x00007ffff304bb6e in uv__io_poll (loop=loop@entry=0x555555c7b670, timeout=1000) at src/unix/linux-core.c:227
#3  0x00007ffff3041394 in uv_run (loop=0x555555c7b670, mode=mode@entry=UV_RUN_DEFAULT) at src/unix/core.c:352
#4  0x00007ffff2edb826 in __pyx_f_6uvloop_4loop_4Loop___run (__pyx_v_self=0x7ffff2c18028, 
    __pyx_v_mode=UV_RUN_DEFAULT) at uvloop/loop.c:11736
#5  0x00007ffff2fed6e8 in __pyx_f_6uvloop_4loop_4Loop__run (__pyx_v_self=0x7ffff2c18028, 
    __pyx_v_mode=UV_RUN_DEFAULT) at uvloop/loop.c:12205
#6  0x00007ffff2effbcd in __pyx_pf_6uvloop_4loop_4Loop_24run_forever (__pyx_v_self=0x7ffff2c18028)
    at uvloop/loop.c:25171
#7  __pyx_pw_6uvloop_4loop_4Loop_25run_forever (__pyx_v_self=0x7ffff2c18028, unused=<optimized out>)
    at uvloop/loop.c:24957
#8  0x00007ffff2eac36b in __Pyx_PyObject_CallMethO (arg=0x0, func=0x7ffff32b4990) at uvloop/loop.c:137637
#9  __Pyx_PyObject_CallNoArg (func=0x7ffff32b4990) at uvloop/loop.c:6634
#10 0x00007ffff30281c8 in __pyx_pf_6uvloop_4loop_4Loop_44run_until_complete (__pyx_v_future=0x7ffff32c5158, 
    __pyx_v_self=<optimized out>) at uvloop/loop.c:26507
#11 __pyx_pw_6uvloop_4loop_4Loop_45run_until_complete (__pyx_v_self=<optimized out>, 
    __pyx_v_future=<optimized out>) at uvloop/loop.c:26195
#12 0x0000555555647e64 in _PyCFunction_FastCallDict (kwargs=0x0, nargs=1, args=0x7ffff39d55a0, 
    func_obj=0x7ffff32b41f8) at Objects/methodobject.c:209
#13 _PyCFunction_FastCallKeywords (func=func@entry=0x7ffff32b41f8, stack=stack@entry=0x7ffff39d55a0, nargs=1, 
    kwnames=kwnames@entry=0x0) at Objects/methodobject.c:295
#14 0x00005555556da6fe in call_function (pp_stack=pp_stack@entry=0x7fffffffd0a8, oparg=oparg@entry=1, 
    kwnames=kwnames@entry=0x0) at Python/ceval.c:4798
#15 0x00005555556dfea3 in _PyEval_EvalFrameDefault (f=<optimized out>, throwflag=<optimized out>)
    at Python/ceval.c:3284
#16 0x00005555556da34d in PyEval_EvalFrameEx (throwflag=0, f=0x7ffff39d5418) at Python/ceval.c:718
#17 _PyEval_EvalCodeWithName (_co=0x7ffff7ed3db0, globals=globals@entry=0x7ffff7f58240, locals=locals@entry=0x0, 
    args=<optimized out>, argcount=0, kwnames=kwnames@entry=0x0, kwargs=0x7ffff7f86ba0, kwcount=0, kwstep=1, 
    defs=0x0, defcount=0, kwdefs=0x0, closure=0x0, name=0x7ffff7e9eb90, qualname=0x7ffff7e9eb90)
    at Python/ceval.c:4128
#18 0x00005555556da614 in fast_function (kwnames=0x0, nargs=<optimized out>, stack=<optimized out>, 
    func=0x7ffff32bfd08) at Python/ceval.c:4939
#19 call_function (pp_stack=pp_stack@entry=0x7fffffffd338, oparg=oparg@entry=0, kwnames=kwnames@entry=0x0)
    at Python/ceval.c:4819
#20 0x00005555556dfea3 in _PyEval_EvalFrameDefault (f=<optimized out>, throwflag=<optimized out>)
    at Python/ceval.c:3284
#21 0x00005555556da34d in PyEval_EvalFrameEx (throwflag=0, f=0x7ffff7f86a20) at Python/ceval.c:718
#22 _PyEval_EvalCodeWithName (_co=_co@entry=0x7ffff7ed3e40, globals=globals@entry=0x7ffff7f6f150, 
    locals=locals@entry=0x7ffff7ed3e40, args=args@entry=0x0, argcount=argcount@entry=0, kwnames=kwnames@entry=0x0, 
    kwargs=0x8, kwcount=0, kwstep=2, defs=0x0, defcount=0, kwdefs=0x0, closure=0x0, name=0x0, qualname=0x0)
    at Python/ceval.c:4128
#23 0x00005555556db1c3 in PyEval_EvalCodeEx (closure=0x0, kwdefs=0x0, defcount=0, defs=0x0, kwcount=0, kws=0x0, 
    argcount=0, args=0x0, locals=locals@entry=0x7ffff7ed3e40, globals=globals@entry=0x7ffff7f6f150, 
    _co=_co@entry=0x7ffff7ed3e40) at Python/ceval.c:4149
#24 PyEval_EvalCode (co=co@entry=0x7ffff7ed3e40, globals=globals@entry=0x7ffff7f58240, 
    locals=locals@entry=0x7ffff7f58240) at Python/ceval.c:695
#25 0x00005555555b2eb9 in run_mod (arena=0x7ffff7f6f150, flags=0x7fffffffd63c, locals=0x7ffff7f58240,

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions