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

IDLE crashes when KeyError is raised during calltip generation #82870

Closed
mr-nfamous mannequin opened this issue Nov 4, 2019 · 8 comments
Closed

IDLE crashes when KeyError is raised during calltip generation #82870

mr-nfamous mannequin opened this issue Nov 4, 2019 · 8 comments
Assignees
Labels
3.7 (EOL) end of life 3.8 only security fixes 3.9 only security fixes topic-IDLE type-bug An unexpected behavior, bug, or error

Comments

@mr-nfamous
Copy link
Mannequin

mr-nfamous mannequin commented Nov 4, 2019

BPO 38689
Nosy @terryjreedy, @taleinat, @mr-nfamous, @miss-islington
PRs
  • bpo-38689: avoid IDLE hanging when calltip fails getting a signature #17152
  • [3.8] bpo-38689: avoid IDLE hanging when calltip fails getting a signature (GH-17152) #19353
  • [3.7] bpo-38689: avoid IDLE hanging when calltip fails getting a signature (GH-17152) #19354
  • 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 = 'https://github.com/terryjreedy'
    closed_at = <Date 2020-04-04.20:37:09.429>
    created_at = <Date 2019-11-04.23:45:56.427>
    labels = ['3.8', 'expert-IDLE', 'type-bug', '3.7', '3.9']
    title = 'IDLE crashes when KeyError is raised during calltip generation'
    updated_at = <Date 2020-04-04.20:37:09.428>
    user = 'https://github.com/mr-nfamous'

    bugs.python.org fields:

    activity = <Date 2020-04-04.20:37:09.428>
    actor = 'terry.reedy'
    assignee = 'terry.reedy'
    closed = True
    closed_date = <Date 2020-04-04.20:37:09.429>
    closer = 'terry.reedy'
    components = ['IDLE']
    creation = <Date 2019-11-04.23:45:56.427>
    creator = 'bup'
    dependencies = []
    files = []
    hgrepos = []
    issue_num = 38689
    keywords = ['patch']
    message_count = 8.0
    messages = ['355983', '356008', '356010', '356592', '365737', '365739', '365740', '365779']
    nosy_count = 4.0
    nosy_names = ['terry.reedy', 'taleinat', 'bup', 'miss-islington']
    pr_nums = ['17152', '19353', '19354']
    priority = 'normal'
    resolution = 'fixed'
    stage = 'resolved'
    status = 'closed'
    superseder = None
    type = 'behavior'
    url = 'https://bugs.python.org/issue38689'
    versions = ['Python 3.7', 'Python 3.8', 'Python 3.9']

    @mr-nfamous
    Copy link
    Mannequin Author

    mr-nfamous mannequin commented Nov 4, 2019

    When the following program has been input (into 32 bit 3.8.0 Python running on windows 10), all IDLE processes and windows will immediately and irrevocably hang the instant the open parentheses at the end of the statement "Object(" is rendered.

    However that's just my 90% sure guess of the cause, based on
    how when the regular dict from this example is swapped with one that raises AttributeError instead of KeyError, a crash no longer occurs. Quite perplexing, seeing as neither exception is handled in get_argspec.

    >>> if 1:
        from idlelib.calltip import get_argspec
        class Type(type):
            __class__ = property((__class__:={}).__getitem__,__class__.__setitem__)
        class Object(metaclass=Type):
            __slots__ = '__class__'
        get_argspec(Object)
    
        
    Traceback (most recent call last):
      File "<pyshell#41>", line 7, in <module>
        get_argspec(Object)
      File "C:\Python38\lib\idlelib\calltip.py", line 141, in get_argspec
        argspec = str(inspect.signature(fob))
      File "C:\Python38\lib\inspect.py", line 3093, in signature
        return Signature.from_callable(obj, follow_wrapped=follow_wrapped)
      File "C:\Python38\lib\inspect.py", line 2842, in from_callable
        return _signature_from_callable(obj, sigcls=cls,
      File "C:\Python38\lib\inspect.py", line 2218, in _signature_from_callable
        if isinstance(obj, types.MethodType):
    KeyError: <class '__main__.Object'>

    @mr-nfamous mr-nfamous mannequin added the 3.8 only security fixes label Nov 4, 2019
    @mr-nfamous mr-nfamous mannequin assigned terryjreedy Nov 4, 2019
    @mr-nfamous mr-nfamous mannequin added the topic-IDLE label Nov 4, 2019
    @terryjreedy
    Copy link
    Member

    Since isinstance(Object.__call__, types.MethodType) is False, the 'fob' in 'inspect.signature(fob)' is Object. (See the initial get_argspec code.) Indeed, 'inspect.signature(Object)' results in the traceback following inspect.signature(fob) and 'isinstance(Object, types.MethodType)' results in the last line thereof. Not returning 'False' strikes me as maybe a bug in 'isinstance'. Have you opened a report for this?

    Directly importing and executing idlelib code is not supported (its is 'private'), but entering 'Object(' to cause IDLE to make the same call is. And the result is worse than the exception. The IDLE gui process hangs, waiting for the response from the socket connection to the user code process that never comes. This is clearly a bug, regardless of whether the user code is buggy.

    The relevant section of get_argspec is

    try:
        argspec = str(inspect.signature(fob))
    except ValueError as err:
        msg = str(err)
        if msg.startswith(_invalid_method):
            return _invalid_method
    

    Signature() is documented as returning either ValueError or TypeError, and with the 'bug' in isinstance, others are possible. So any error should be caught. (The default of falling through and checking for a docstring signature is correct.)

    @terryjreedy
    Copy link
    Member

    Further experiments suggest a fix for the hang, which is not specific to this example. See new issue bpo-38695.

    @terryjreedy terryjreedy added 3.7 (EOL) end of life 3.9 only security fixes type-bug An unexpected behavior, bug, or error labels Nov 5, 2019
    @taleinat
    Copy link
    Contributor

    See PR #61354 with a fix for the uncaught exception in getargspec().

    @terryjreedy
    Copy link
    Member

    New changeset 52013e5 by Tal Einat in branch 'master':
    bpo-38689: avoid IDLE hanging when calltip fails getting a signature (GH-17152)
    52013e5

    @miss-islington
    Copy link
    Contributor

    New changeset 681044a by Miss Islington (bot) in branch '3.7':
    bpo-38689: avoid IDLE hanging when calltip fails getting a signature (GH-17152)
    681044a

    @miss-islington
    Copy link
    Contributor

    New changeset 1533772 by Miss Islington (bot) in branch '3.8':
    bpo-38689: avoid IDLE hanging when calltip fails getting a signature (GH-17152)
    1533772

    @terryjreedy
    Copy link
    Member

    get_argspec accesses the user object 3 times. The first, ob.__call__ was already wrapped in try-except. The second, signature(ob or ob.__call) is wrapped by this issue. It also adds a new test based on Dan's example. The third is (ob or ob.__call__).__doc__. I did not wrap this because I could not create an example for which this fails. There seems to be some special casing of this special attribute so that its default is None.

    I opened bpo-40180 for the isinstance bug and bpo-40181 for further get_argspec changes, in particular, removing the positional-only '/' note.

    @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
    3.7 (EOL) end of life 3.8 only security fixes 3.9 only security fixes topic-IDLE type-bug An unexpected behavior, bug, or error
    Projects
    None yet
    Development

    No branches or pull requests

    3 participants