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

Crash when using typing and daemon threads #116514

Open
nineteendo opened this issue Mar 8, 2024 · 12 comments
Open

Crash when using typing and daemon threads #116514

nineteendo opened this issue Mar 8, 2024 · 12 comments
Labels
topic-typing type-crash A hard crash of the interpreter, possibly with a core dump

Comments

@nineteendo
Copy link
Contributor

nineteendo commented Mar 8, 2024

Crash report

What happened?

When I run this code on Python 3.11 it runs fine, but if I import typing_minimal (or typing) in reader.py I get this error:

Fatal Python error: _enter_buffered_busy: could not acquire lock for <_io.BufferedReader name='<stdin>'> at interpreter shutdown, possibly due to daemon threads
Python runtime state: finalizing (tstate=0x00007fff13ab6960)

Current thread 0x00003944 (most recent call first):
  <no Python frame>

main.py:

import reader
from typing_minimal import Generic, TypeVar

VALUE = TypeVar("VALUE")


class BaseClass(Generic[VALUE]):
    def __init__(self):
        pass


class SubClass(BaseClass[VALUE]):
    pass


reader.thread.start()

reader.py:

from sys import stdin
from threading import Thread

# BUG: I get an error when I assign this:
# typing_minimal = __import__("typing_minimal")


thread = Thread(target=lambda: stdin.buffer.read(), daemon=True)

typing_minimal.py:

from functools import lru_cache, wraps


def _tp_cache(func):
    cached = lru_cache()(func)

    @wraps(func)
    def inner(*args, **kwds):
        return cached(*args, **kwds)

    return inner


class TypeVar:
    def __init__(self, _):
        pass


class _GenericAlias:
    def __init__(self, origin):
        self.origin = origin

    def __eq__(self, other):
        if isinstance(other, _GenericAlias):
            return self.origin is other.origin

        return NotImplemented

    def __hash__(self):
        return hash(self.origin)

    def __mro_entries__(self, _):
        return (self.origin,)


class Generic:
    @_tp_cache
    def __class_getitem__(cls, *_):
        return _GenericAlias(cls)

I don't understand how this is even possible.

CPython versions tested on:

3.11

Operating systems tested on:

macOS, Windows

@nineteendo nineteendo added the type-crash A hard crash of the interpreter, possibly with a core dump label Mar 8, 2024
@sobolevn
Copy link
Member

sobolevn commented Mar 8, 2024

_lru_cache_wrapper uses RLock() inside, so this might be the cause when combined with a daemon thread.

@JelleZijlstra
Copy link
Member

What is typing_minimal here? That's not in the stdlib and a cursory Google search didn't turn up anything.

@sobolevn
Copy link
Member

sobolevn commented Mar 8, 2024

It is a simplification of typing.py to make the bug more obvious :)

@JelleZijlstra
Copy link
Member

It's in the comment... sorry I missed that.

@nineteendo
Copy link
Contributor Author

Any idea why importing typing_minimal in reader.py makes a difference?
__import__("typing_minimal") instead of typing_minimal = __import__("typing_minimal") works fine though.

@JelleZijlstra
Copy link
Member

Possibly some new reference cycle gets created. Reminds me of #115874 though the symptom is different.

@nineteendo
Copy link
Contributor Author

Is there anything I can still help with?

@sobolevn
Copy link
Member

I used this example to reproduce the issue:

from sys import stdin
from threading import Thread


def start_reading():
    Thread(target=stdin.buffer.read, daemon=True).start()

start_reading()

It still gives me:

» ./python.exe main.py
Fatal Python error: _enter_buffered_busy: could not acquire lock for <_io.BufferedReader name='<stdin>'> at interpreter shutdown, possibly due to daemon threads
Python runtime state: finalizing (tstate=0x000000010553bdd8)

Current thread 0x00000001e4b85300 (most recent call first):
  <no Python frame>
[1]    92981 abort      ./python.exe main.py
                                          

So, now I think that this is a related to #113964

@nineteendo
Copy link
Contributor Author

nineteendo commented Mar 13, 2024

The code at the top is simplified as much as possible. So this doesn't result in an error without the other changes (which is kind of strange too):

from sys import stdin
from threading import Thread


def read():
    stdin.buffer.read()


Thread(target=read, daemon=True).start()

@nineteendo
Copy link
Contributor Author

This issue isn't so much about the interpreter crashing, but the fact that it crashes when I import typing_minimal in reader.py.

@nineteendo

This comment was marked as outdated.

@nineteendo nineteendo closed this as not planned Won't fix, can't repro, duplicate, stale Apr 10, 2024
@JelleZijlstra
Copy link
Member

It's a crash so it should be fixed. Hopefully someone will come along eventually and fix it, or other changes to the interpreter will fix this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
topic-typing type-crash A hard crash of the interpreter, possibly with a core dump
Projects
None yet
Development

No branches or pull requests

3 participants