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

Importing the keyring module in some Linux configurations can stall for 25 seconds or so #473

Closed
siebenmann opened this issue Oct 28, 2020 · 3 comments

Comments

@siebenmann
Copy link

Describe the bug
On some Unix configurations, simply importing the keyring module can cause the Python interpreter for 25 seconds or so. This has been reported on Wayland sessions and in remote logins (eg in pypa/pip#8485). Whether this happens appears to depend on the Linux involved; it appears to occur on Fedora but not necessarily Ubuntu. This may be considered a duplicate of #403, but I think it's a more specific issue.

To Reproduce
Steps to reproduce the behavior:

  1. Arrange a Fedora machine with the kf5-kwallet package installed.
  2. Remotely log in to the machine when there is no console login session.
  3. Run time python3 -c "import keyring" and observe it takes 25 seconds or so.

Expected behavior
This should complete without stalling, especially for 25 seconds or so.

Environment

  • OS: Fedora 32
$ pip list | grep keyring
keyring            21.3.1
$ keyring --list-backends
keyring.backends.fail.Keyring (priority: 0)
keyring.backends.chainer.ChainerBackend (priority: -1)
keyring.backends.SecretService.Keyring (priority: 5)

However code inspection suggests that this will happen with the current git version, although I'm not sure.

Additional context
The problem happens in backends/kwallet.py, where the priority() class method attempts to make a DBus connection to the org.kde.kwalletd5 DBus service. On some Linux systems (possibly it requires systemd) with kwalletd installed, this DBus call will trigger an attempt to start kwalletd, which fails but times out very slowly. You can duplicate this with a simple DBus call:

>>> from dbus.mainloop.glib import DBusGMainLoop
>>> bus = dbus.SessionBus(mainloop=DBusGMainLoop())
>>> bus.get_object('org.kde.kwalletd5', '/modules/kwalletd5')

The call path of this on import is through core.py's call to init_backend(), which then uses backend.by_priority() to try to get the priority for every backend, which triggers the call to kwallet.py's priority().

@takluyver
Copy link
Contributor

Perhaps when selecting the backend it would make sense to check if the service is already running (bus.name_has_owner('org.kde.kwalletd5')) or is available to be started through D-Bus ('org.kde.kwalletd5' in bus.list_activatable_names()). I think those should both be safe to check without the bus trying to launch it.

If you end up trying to use the Kwallet backend anyway, this just shifts the delay to when you access the keyring. But it would be an improvement for cases where it picks another backend (if both are available, SecretStorage is preferred for users not on KDE), and cases where keyring is imported but nothing tries to use it.

The possible downside is that this approach might choose the Kwallet backend when Kwallet is present but somehow broken, whereas the current approach of talking to it before deciding it's viable might fall back to another backend. But I'm not sure that's really a drawback - I don't want the guessing to be too smart.

@mitya57
Copy link
Collaborator

mitya57 commented Nov 6, 2020

@takluyver Good idea, thanks for the suggestion! I think we can do this for both KWallet and SecretService backends, so this will also fix #162.

@jaraco What do you think about this?

@jaraco
Copy link
Owner

jaraco commented Nov 6, 2020

That sounds good to me. Agreed it would be highly desirable not to block on startup.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants