-
Notifications
You must be signed in to change notification settings - Fork 15
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
wakepy freezes ubuntu when using it repeatedly (10k times) in a loop on Ubuntu (Gnome SessionManager) #277
Comments
Fixes the error with Gnome SessionManager based keepawake (issue #276) DBus Adapters ------------- * All DBusAdapters now have to keep reference to the connection(s). This was required as if the connection instance was garbage collected, the inhibit cookie created by Gnome SessionManager was wiped. * The DBusAdapter class now has _get_connection(bus) method or getting a connection instance for an adapter. * The DBusAdapter subclasses now must implement a _create_new_connection(bus) method. Other ---- Temporarily ignore warnings in tests/integration/conftest.py while running gc.collect(). This should be addressed later (likely as part of #277)
Debugging: bottom-upTrying to reproduce the behavior with smallest amount of code possible. 1) It's not caused by just opening and closing connectionsThis causes no problems: from jeepney.io.blocking import open_dbus_connection
for i in range(10_000):
print(i)
connection = open_dbus_connection(bus="SESSION")
connection.close() 2) A simple DBus method call does not cause the issueThis causes no problems: from jeepney import DBusAddress, new_method_call
from jeepney.io.blocking import open_dbus_connection
from jeepney.wrappers import unwrap_msg
for i in range(10_000):
print(i)
connection = open_dbus_connection(bus="SESSION")
addr = DBusAddress(
object_path="/org/freedesktop/DBus",
bus_name="org.freedesktop.DBus",
interface="org.freedesktop.DBus",
)
msg = new_method_call(
addr,
method="ListNames",
signature=None,
body=None,
)
reply = connection.send_and_get_reply(msg, timeout=1)
resp = unwrap_msg(reply)
connection.close() 3) Inhibit + Uninhibit DBus calls to SessionManagerThis will freeze my Ubuntu 22.04 laptop with GNOME 42.9 in around 400-600 iterations: from jeepney import DBusAddress, new_method_call
from jeepney.io.blocking import open_dbus_connection
from jeepney.wrappers import unwrap_msg
addr = DBusAddress(
object_path="/org/gnome/SessionManager",
bus_name="org.gnome.SessionManager",
interface="org.gnome.SessionManager",
)
def call(method, signature=None, body=None):
msg = new_method_call(
addr,
method=method,
signature=signature,
body=body,
)
reply = connection.send_and_get_reply(msg, timeout=1)
return unwrap_msg(reply)
for i in range(10_000):
connection = open_dbus_connection(bus="SESSION")
cookie = call(
method="Inhibit",
signature="susu", # "app_id", "toplevel_xid", "reason", "flags"
body=("wakepy", 42, "wakelock active", 8),
)[0]
inhibitors = call(
method="GetInhibitors",
)[0]
print(f"{i}, {cookie=}, inhibitors = {len(inhibitors)}")
call(
method="Uninhibit",
signature="u", # "cookie"
body=(cookie,),
)
inhibitors = call(
method="GetInhibitors",
)[0]
print(f" {i}, {cookie=}, inhibitors = {len(inhibitors)}")
connection.close() I can see that the number of inhibitors is either 1 or 2, so these are not piling up:
Variations:
4) Test with dbus library instead of jeepneyThis also freezes the system in 400-600 cycles: import dbus
for i in range(10_000):
session_bus = dbus.SessionBus()
proxy = session_bus.get_object(
"org.gnome.SessionManager", "/org/gnome/SessionManager"
)
cookie = proxy.get_dbus_method(
"Inhibit", dbus_interface="org.gnome.SessionManager"
)("wakepy", 42, "wakelock active", 8)
inhibitors = proxy.get_dbus_method(
"GetInhibitors", dbus_interface="org.gnome.SessionManager"
)()
print(f"{i}, {cookie=}, inhibitors = {len(inhibitors)}")
proxy.get_dbus_method("Uninhibit", dbus_interface="org.gnome.SessionManager")(
int(cookie)
)
inhibitors = proxy.get_dbus_method(
"GetInhibitors", dbus_interface="org.gnome.SessionManager"
)()
print(f" {i}, {cookie=}, inhibitors = {len(inhibitors)}")
session_bus.close() SummaryIt looks like it's not caused by jeepney since jeepney can process other dbus calls (ListNames example above) just fine. This also is reproduced with dbus-python, so it looks like it's connected to GNOME. I created an issue in the GNOME GitLab repository: gnome-settings-daemon/#798. I'll wait comments there before proceeding with this. |
Using con.close() + gc.collect() and just jeepneyNote: removing the import gc
from jeepney import DBusAddress, new_method_call
from jeepney.io.blocking import open_dbus_connection
from jeepney.wrappers import unwrap_msg
addr = DBusAddress(
object_path="/org/gnome/SessionManager",
bus_name="org.gnome.SessionManager",
interface="org.gnome.SessionManager",
)
def call(method, signature=None, body=None):
msg = new_method_call(
addr,
method=method,
signature=signature,
body=body,
)
reply = connection.send_and_get_reply(msg, timeout=1)
return unwrap_msg(reply)
for i in range(10_000):
connection = open_dbus_connection(bus="SESSION")
cookie = call(
method="Inhibit",
signature="susu", # "app_id", "toplevel_xid", "reason", "flags"
body=("wakepy", 42, "wakelock active", 8),
)[0]
inhibitors = call(
method="GetInhibitors",
)[0]
print(f"{i}, {cookie=}, inhibitors = {len(inhibitors)}")
call(
method="Uninhibit",
signature="u", # "cookie"
body=(cookie,),
)
inhibitors = call(
method="GetInhibitors",
)[0]
print(f" {i}, {cookie=}, inhibitors = {len(inhibitors)}")
connection.close()
gc.collect() so why does: from wakepy import keep
for i in range(10_000):
with keep.running() as m:
print(i)
|
Just tested on the same system and also the "org.freedesktop.ScreenSaver" (keep.presenting mode) behaves exactly the same. It's likely that the org.freedesktop.ScreenSaver interface is registered by some Gnome process when running Gnome, so this is somewhat expected. While this is an annoying bug, I don't know if it's wakepy, jeepney, dbus, CPython or Gnome (or something else) where the fix could and should be made. It's also been there already in wakepy 0.7.x (using org.freedesktop.ScreenSaver), so I think it's okay to proceed with releasing 0.8.0 with this. Luckily it's relatively uncommon to inhibit sleep hundreds or thousands times. I hope to gather more understanding on this and fix it or find an alternative way for inhibiting sleep on Gnome. |
Adding delay between callsAdding delay between function calls seems to fix the problem. I left my computer to do this (with wakepy on) for few hours: code with four sleeps in itimport time
from jeepney import DBusAddress, new_method_call
from jeepney.io.blocking import open_dbus_connection
from jeepney.wrappers import unwrap_msg
addr = DBusAddress(
object_path="/org/gnome/SessionManager",
bus_name="org.gnome.SessionManager",
interface="org.gnome.SessionManager",
)
def call(method, signature=None, body=None):
msg = new_method_call(
addr,
method=method,
signature=signature,
body=body,
)
reply = connection.send_and_get_reply(msg, timeout=1)
return unwrap_msg(reply)
for i in range(10_000):
connection = open_dbus_connection(bus="SESSION")
time.sleep(0.05) #1
cookie = call(
method="Inhibit",
signature="susu", # "app_id", "toplevel_xid", "reason", "flags"
body=("wakepy", 42, "wakelock active", 8),
)[0]
time.sleep(0.2) #2
print(f"{i}, {cookie=}")
call(
method="Uninhibit",
signature="u", # "cookie"
body=(cookie,),
)
time.sleep(0.5) #3
connection.close()
time.sleep(0.5) #4 When I came back, system was not suffering of any kind of slowness. So most likely this is about doing the function calls fast and repeatedly. The fact that calling Narrowing down the problemHere are some results when removing one of the sleeps: single sleep removed
two sleeps removed
three sleeps removed
SummaryAdding sleep anywhere within the full cycle (open connection, inhibit sleep, uninhibit, close connection) seems to fix the problem. Shortest sleep tried was 50ms. In addition to this, I tested with wakepy with 50ms sleep and 80k iterations: for i in range(80_000):
with keep.running() as m:
print(i, m.used_method)
time.sleep(0.05) and could not reproduce any slow-downs. This seems to be a non-issue as the sleep is typically inhibited for a long-running task, and it's typical to have only one or few locks with one task. |
Found this one accidentally when debugging #276. This will freeze Ubuntu 22.04, GNOME 42.9, development version of 0.8.0 wakepy (for example c574e52):
About the behavior:
Task:
The text was updated successfully, but these errors were encountered: