Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[sqlite3] use unraisable exceptions in callbacks #89986

Closed
erlend-aasland opened this issue Nov 17, 2021 · 2 comments
Closed

[sqlite3] use unraisable exceptions in callbacks #89986

erlend-aasland opened this issue Nov 17, 2021 · 2 comments
Labels

Comments

@erlend-aasland
Copy link
Contributor

erlend-aasland commented Nov 17, 2021

BPO 45828
Nosy @serhiy-storchaka, @pablogsal, @erlend-aasland
PRs
  • bpo-45828: Use unraisable exceptions within sqlite3 callbacks #29591
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = None
    closed_at = <Date 2022-03-04.20:08:47.676>
    created_at = <Date 2021-11-17.09:42:19.148>
    labels = ['extension-modules', '3.11']
    title = '[sqlite3] use unraisable exceptions in callbacks'
    updated_at = <Date 2022-03-04.20:08:47.675>
    user = 'https://github.com/erlend-aasland'

    bugs.python.org fields:

    activity = <Date 2022-03-04.20:08:47.675>
    actor = 'erlendaasland'
    assignee = 'none'
    closed = True
    closed_date = <Date 2022-03-04.20:08:47.676>
    closer = 'erlendaasland'
    components = ['Extension Modules']
    creation = <Date 2021-11-17.09:42:19.148>
    creator = 'erlendaasland'
    dependencies = []
    files = []
    hgrepos = []
    issue_num = 45828
    keywords = ['patch']
    message_count = 2.0
    messages = ['406459', '407285']
    nosy_count = 3.0
    nosy_names = ['serhiy.storchaka', 'pablogsal', 'erlendaasland']
    pr_nums = ['29591']
    priority = 'normal'
    resolution = 'fixed'
    stage = 'resolved'
    status = 'closed'
    superseder = None
    type = None
    url = 'https://bugs.python.org/issue45828'
    versions = ['Python 3.11']

    @erlend-aasland
    Copy link
    Contributor Author

    erlend-aasland commented Nov 17, 2021

    In order to print tracebacks from exceptions in SQLite callbacks, the sqlite3 extension module provides sqlite3.enable_callback_tracebacks(flag). Setting the flag to True instructs the sqlite3 extension module to PyErr_Print() if an exception occurs during a callback. Else, PyErr_Clear() is called.

    From the sqlite3.enable_callback_tracebacks() docs:

    By default you will not get any tracebacks in user-defined functions,
    aggregates, converters, authorizer callbacks etc. If you want to debug
    them, you can call this function with flag set to True. Afterwards, you
    will get tracebacks from callbacks on sys.stderr. Use False to disable the
    feature again.
    

    Few other exceptions use a similar approach:

        $ grep -r PyErr_Print Modules 
        Modules/_tkinter.c:        PyErr_Print();
        Modules/_testcapimodule.c:        PyErr_Print();
        Modules/main.c:    PyErr_Print();
        Modules/main.c:        PyErr_Print();
        Modules/main.c:        PyErr_Print();
        Modules/_io/bytesio.c:        PyErr_Print();
        Modules/_sqlite/connection.c:        PyErr_Print();
        Modules/_sqlite/cursor.c:                    PyErr_Print();
        Modules/_xxtestfuzz/fuzzer.c:        PyErr_Print();
        Modules/_xxtestfuzz/fuzzer.c:        PyErr_Print();
        Modules/_xxtestfuzz/fuzzer.c:        PyErr_Print();
        Modules/_xxtestfuzz/fuzzer.c:        PyErr_Print();
        Modules/_xxtestfuzz/fuzzer.c:        PyErr_Print();
        Modules/_xxtestfuzz/fuzzer.c:        PyErr_Print();
        Modules/_xxtestfuzz/fuzzer.c:        PyErr_Print();
        Modules/_ctypes/callbacks.c:    PyErr_Print();

    We get a higher hit for unraisable exceptions:

        $ grep -r PyErr_WriteUnraisable Modules | wc -l
          45

    AFAICS, using unraisable exceptions is a better approach.

    Current behaviour:

        Python 3.10.0 (v3.10.0:b494f5935c, Oct  4 2021, 14:59:20) [Clang 12.0.5 (clang-1205.0.22.11)] on darwin
        Type "help", "copyright", "credits" or "license" for more information.
        >>> import sqlite3
        >>> cx = sqlite3.connect(":memory:")
        >>> cx.set_trace_callback(lambda stmt: 5/0)
        >>> cx.execute("select 1")
        <sqlite3.Cursor object at 0x109bba2c0>
        >>> sqlite3.enable_callback_tracebacks(True)
        >>> cx.execute("select 1")
        Traceback (most recent call last):
          File "<stdin>", line 1, in <lambda>
        ZeroDivisionError: division by zero
        <sqlite3.Cursor object at 0x1099046c0>

    With unraisable exceptions:

        Python 3.11.0a2+ (heads/sqlite-unraisable-exceptions-dirty:de29590d6a, Nov 17 2021, 10:29:19) [Clang 13.0.0 (clang-1300.0.29.3)] on darwin
        Type "help", "copyright", "credits" or "license" for more information.
        >>> import sqlite3
        >>> cx = sqlite3.connect(":memory:")
        >>> cx.set_trace_callback(lambda stmt: 5/0)
        >>> cx.execute("select 1")
        <sqlite3.Cursor object at 0x10b1fe720>
        >>> sqlite3.enable_callback_tracebacks(True)
        >>> cx.execute("select 1")
        Exception ignored in: <function <lambda> at 0x10b4e3ee0>
        Traceback (most recent call last):
          File "<stdin>", line 1, in <lambda>
        ZeroDivisionError: division by zero
        <sqlite3.Cursor object at 0x10b1fe840>

    The user experience is mostly unchanged; we get one extra line, telling us that the exception was ignored. Also, users can now use sys.unraisablehook:

        >>> sys.unraisablehook = lambda unraisable: print(unraisable)
        >>> cx.execute("select 1")
        UnraisableHookArgs(exc_type=<class 'ZeroDivisionError'>,     exc_value=ZeroDivisionError('division by zero'), exc_traceback=<traceback object at 0x10b559900>, err_msg=None, object=<function <lambda> at 0x10b4e3ee0>)
        <sqlite3.Cursor object at 0x10b1fe840>

    The only question I have, is if we should deprecate sqlite3.enable_callback_tracebacks() after switching to unraisable exceptions.

    @erlend-aasland erlend-aasland added 3.11 extension-modules C modules in the Modules dir labels Nov 17, 2021
    @pablogsal
    Copy link
    Member

    pablogsal commented Nov 29, 2021

    New changeset c4a69a4 by Erlend Egeberg Aasland in branch 'main':
    bpo-45828: Use unraisable exceptions within sqlite3 callbacks (FH-29591)
    c4a69a4

    @ezio-melotti ezio-melotti transferred this issue from another repository Apr 10, 2022
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Labels
    Projects
    None yet
    Development

    No branches or pull requests

    2 participants