-
Notifications
You must be signed in to change notification settings - Fork 36
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
How to use signals #7
Comments
we have no plan to implement signals, because so far, we have not need it, but if you have a use case, and you would like to share it with us (tell us why you need it, and how you will use them), i'll be happy to look into it and try to support for it. (also patches are always welcome) :D |
My application is super simple, just a systemd services state monitor. User can set which services they want to monitor, and get "real time" notification when the service state changed. |
@awarecan cool, so i think you can get that now with pystemd in the current state, i actually do this in you can check it out in: https://github.com/facebookincubator/pystemd/blob/master/pystemd/run.py#L240-L244 but a quick example (that probably i should eventually add to the example folder could be): Assuming that a unit name import select
from pystemd.systemd1 import Unit
from pystemd.dbuslib import DBus
from pystemd.DBus import Manager as DBusManager
unit = Unit("my_custom_sleep.service")
mstr = (
(
"type='signal',"
"sender='org.freedesktop.systemd1',"
"path='{}',"
"interface='org.freedesktop.DBus.Properties',"
"member='PropertiesChanged'"
)
.format(unit.path.decode())
.encode()
)
with DBus() as monbus, DBusManager(bus=monbus) as man:
man.Monitoring.BecomeMonitor([mstr], 0)
fd = monbus.get_fd()
while True:
select.select([fd], [], [])
m = monbus.process()
if m.is_empty():
continue
m.process_reply(False)
print(m.body)
if m.get_path() == unit.path:
if m.body[1].get(b"SubState") in (b"exited", b"failed", b"dead"):
break and this will dump this lines, each time that one of the properties that emit change... well change...
the code "looks" complex, but its actually quite easy to follow... i think this accomplish what you need, right? |
i forgot, but i actually "ported" busctl monitor to pystemd in this example |
@aleivag Thank you very much for the sample code. I am just following your code and hit that error. Do I have to be root? I don't need that for signal listen in pydbus lib.
|
Googling told me that: ref
|
@awarecan yes you have to be root, i dont think you can subscribe to the system event bus with a regular user (but i may be wrong). if your service belong to the user bus (e.g started with pystemd rely heavily in When run as root i can see mayor events, maybe you can share how you do it with best regards! |
@aleivag here is my implementation base on pydbus, it doesn't need root, and passed on Ubuntu. Subscribe to signal Run GLib MainLoop |
cool, thanks @awarecan i will look at it in the afternoon and see if i can came up with ideas thank you for sharing this!! |
hey, so the good news is that it can be done 🎉 ... the bad-ish news is that i need to expose i was planing to do it either way, the hard part about that is that its implemented as callbacks, and python callbacks in c land are not as trivial as they sound basically because c has no concept of exception, so a python exception can became a c memory leak. once i finish coding this, the result code may look like import select
from pystemd.dbuslib import DBus
from pystemd.systemd1 import Unit
class STATE:
EXIT = False
def process(msg, err=None):
print(msg.body)
if msg.body[1].get(b"SubState") in (b"exited", b"failed", b"dead"):
STATE.EXIT = True
with DBus(False) as dbus:
myunit = Unit('mysleep.service')
dbus.match_signal(
myunit.destination,
myunit.path,
b"org.freedesktop.DBus.Properties",
b"PropertiesChanged",
process, # <-- your function
None, # maybe pass custom python objects as userdata?
)
fd = dbus.get_fd()
while not STATE.EXIT:
select.select([fd], [], []) # wait for message
dbus.process() # execute the whole message please notice that that is just an idea, it may end up looking a little bit different. will post here when the code is merged |
hey @awarecan thanks for the patience... the code has been merged, you can test it... a working example can be found in https://github.com/facebookincubator/pystemd/blob/master/examples/monitor_from_signal.py i test this, and i can see properties changes on units from the system bus without been root... Hope this helps... (please notice that the example has detail implementation, that may or may not fit your project)... :D |
Heads up! by implementing it as |
I am following your example, had met several bumps
|
For def process_message(message, error=None, userdata=None):
pass
# some other codes
try:
with DBus() as bus:
bus.match_signal(
b'org.freedesktop.systemd1',
b'/org/freedesktop/systemd1/unit/bluetooth_2eservice',
b'org.freedesktop.DBus.Properties',
b'PropertiesChanged',
process_message,
)
fd = bus.get_fd()
while True:
select.select([fd], [], [])
bus.process()
except Exception as error:
_LOGGER.error(error) My systemd is 237 by the way.
|
yeah segfaults are not catchable... that is super weird, let me try to reproduce... |
so i was not able to reproduce, but i'm running v238, will try get a hold of a 237 machine to test, so far the only theory i have is that the dealloc methoc is breaking you. you can even try to remove it yourself, just keep in mind that that is the only thing that is preventing a big memory leak on each new message anyway i will do more digging one a have a v237 in my hands! |
Shall we follow the principle "whoever alloc the memory should dealloc it" (Don't know if there is a fancy word for this) here? m was alloc-ed in libsystemd, so that we should not dealloc it IMO. |
Comment out Everything worked |
i'm both happy (that commenting out makes it work) and sad (i have to make this work on systemd <237 and make a clever de-allocation). The reason why we did the deallocate, is because normally "we allocated" the msg struct. in the callback case that is not the case anymore, since we have no real way of allocating the struct and tehn hand it over to systemd... i have some ideas, but will sleep on them... thanks for helping debug! |
hi @awarecan 👍 def process_message(message, error=None, userdata=None):
pass and not when your callback is
when i implemented this, my logic was to give the user the chance to call with that change you will not see the problem, and the we return the ownership of the msg to the signal_callback . note: to reproduce i got a debian strech and isntalled systemd with the backports Thanks! |
It sounds right. I don't have access to my work now, but I called msg.process_reply(False) actually. |
It looks like when you processing interface, you ignored signal at all.
https://github.com/facebookincubator/pystemd/blob/628655ae61dff66b39feed52c89e0bfda00c4f38/pystemd/base.py#L199-L219
So, is there any support for signal now? Any plan to add the support?
I am looking for use your library, but I would not use it without support of signal that is very important for my project (current base on pydbus, but I would prefer a library doesn't depends on python-gi)
The text was updated successfully, but these errors were encountered: