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

Change weird behavior of PyModule_AddObject() #71058

Closed
serhiy-storchaka opened this issue Apr 27, 2016 · 9 comments
Closed

Change weird behavior of PyModule_AddObject() #71058

serhiy-storchaka opened this issue Apr 27, 2016 · 9 comments
Labels
extension-modules C modules in the Modules dir interpreter-core (Objects, Python, Grammar, and Parser dirs) type-feature A feature request or enhancement

Comments

@serhiy-storchaka
Copy link
Member

BPO 26871
Nosy @encukou, @skrah, @serhiy-storchaka
Files
  • pymodule_addobject.patch
  • pymodule_addobject_2.patch
  • 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 2021-08-17.14:14:27.188>
    created_at = <Date 2016-04-27.17:52:51.529>
    labels = ['extension-modules', 'interpreter-core', 'type-feature']
    title = 'Change weird behavior of PyModule_AddObject()'
    updated_at = <Date 2021-08-17.14:14:27.186>
    user = 'https://github.com/serhiy-storchaka'

    bugs.python.org fields:

    activity = <Date 2021-08-17.14:14:27.186>
    actor = 'petr.viktorin'
    assignee = 'none'
    closed = True
    closed_date = <Date 2021-08-17.14:14:27.188>
    closer = 'petr.viktorin'
    components = ['Extension Modules', 'Interpreter Core']
    creation = <Date 2016-04-27.17:52:51.529>
    creator = 'serhiy.storchaka'
    dependencies = []
    files = ['42632', '42639']
    hgrepos = []
    issue_num = 26871
    keywords = ['patch']
    message_count = 9.0
    messages = ['264384', '264386', '264393', '264394', '264404', '264423', '264432', '264535', '399752']
    nosy_count = 3.0
    nosy_names = ['petr.viktorin', 'skrah', 'serhiy.storchaka']
    pr_nums = []
    priority = 'normal'
    resolution = 'fixed'
    stage = 'resolved'
    status = 'closed'
    superseder = None
    type = 'enhancement'
    url = 'https://bugs.python.org/issue26871'
    versions = ['Python 3.6']

    @serhiy-storchaka
    Copy link
    Member Author

    PyModule_AddObject() has weird and counterintuitive behavior. It steals a reference only on success. The caller is responsible to decref it on error. This behavior was not documented and inconsistent with the behavior of other functions stealing a reference (PyList_SetItem() and PyTuple_SetItem()). Seems most developers don't use this function correctly, since only in few places in the stdlib a reference is decrefed explicitly after PyModule_AddObject() failure.

    This weird behavior was first reported in bpo-1782, and changing it was proposed. Related bugs in PyModule_AddIntConstant() and PyModule_AddStringConstant() were fixed, but the behavior of PyModule_AddObject() was not changed and not documented.

    This issue is opened for gradual changing the behavior of PyModule_AddObject(). Proposed patch introduces new macros PY_MODULE_ADDOBJECT_CLEAN that controls the behavior of PyModule_AddObject() as PY_SSIZE_T_CLEAN controls the behavior of PyArg_Parse* functions. If the macro is defined before including "Python.h", PyModule_AddObject() steals a reference unconditionally. Otherwise it steals a reference only on success, and the caller is responsible for decref'ing it on error (current behavior). This needs minimal changes to source code if PyModule_AddObject() was used incorrectly (i.e. as documented), and keep the code that explicitly decref a reference after PyModule_AddObject() working correctly.

    Use of PyModule_AddObject() without defining PY_MODULE_ADDOBJECT_CLEAN is declared deprecated (or we can defer this to 3.7). In the distant future (after dropping the support of 2.7) the old behavior will be dropped.

    See also a discussion on Python-Dev: http://comments.gmane.org/gmane.comp.python.devel/157545 .

    @serhiy-storchaka serhiy-storchaka added extension-modules C modules in the Modules dir interpreter-core (Objects, Python, Grammar, and Parser dirs) type-feature A feature request or enhancement labels Apr 27, 2016
    @skrah
    Copy link
    Mannequin

    skrah mannequin commented Apr 27, 2016

    I think the current behavior is good for error handling by goto,
    which is common for module initialization.

    Please don't change this.

    @serhiy-storchaka
    Copy link
    Member Author

    Idiomatic code is

    if (PyModule_AddObject(module, "name", create_new_object()) < 0)
        goto error;
    

    If you already have a reference and need to use it later:

        obj = create_new_object();
        ... /* use obj */
        Py_INCREF();
        if (PyModule_AddObject(module, "name", create_new_object()) < 0)
            goto error;
        ... /* use obj */
        Py_DECREF(obj);
    
    error:
        Py_XDECREF(obj);

    Many current code use above idioms, but it doesn't work as expected.

    It is almost impossible to write correct code with current behavior. And _decimal.c is not an exception, it has leaks.

    @skrah
    Copy link
    Mannequin

    skrah mannequin commented Apr 27, 2016

    Your definition of correctness is very odd. The "leaks" you are talking
    about are single references in case of a module initialization failure,
    in which case you are likely to have much bigger problems.

    Please take _decimal out of this patch, it's a waste of time.

    @skrah
    Copy link
    Mannequin

    skrah mannequin commented Apr 27, 2016

    It seems that the patch also introduces a segfault if PyLong_FromSsize_t() returns NULL.

    @serhiy-storchaka
    Copy link
    Member Author

    It seems that the patch also introduces a segfault if PyLong_FromSsize_t() returns NULL.

    Good catch Stefan! Py_XDECREF ahould be used instead of Py_DECREF in _PyModule_AddObject().

    @serhiy-storchaka
    Copy link
    Member Author

    Removed changes in _decimal.c and deprecation. Used Py_XDECREF in _PyModule_AddObject().

    @skrah
    Copy link
    Mannequin

    skrah mannequin commented Apr 29, 2016

    Serhiy, I'm sorry that I overreacted here. You're doing great work for
    Python -- we just happen to disagree on this one particular issue.

    I think there were some proponents on python-dev, perhaps they'll show
    up and discuss the details.

    @encukou
    Copy link
    Member

    encukou commented Aug 17, 2021

    Since #23122, there is PyModule_AddObjectRef doesn't steal a reference.
    PyModule_AddObject is discouraged in the docs, but not formally deprecated. (As Stefan notes, the leaks are single references in case of a module initialization failure -- the cost of using the API incorrectly is very small; requiring everyone to change their code because it was possible to misuse it is overkill.)

    See https://docs.python.org/3.10/c-api/module.html#c.PyModule_AddObjectRef

    I think this is enough to close the issue.

    @encukou encukou closed this as completed Aug 17, 2021
    @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
    extension-modules C modules in the Modules dir interpreter-core (Objects, Python, Grammar, and Parser dirs) type-feature A feature request or enhancement
    Projects
    None yet
    Development

    No branches or pull requests

    2 participants