Python libmm problems

Colin Helliwell colin.helliwell at
Thu Sep 14 14:35:22 UTC 2017

> On 13 September 2017 at 19:39 Dan Williams <dcbw at> wrote:
> The two major patterns for doing all of this are (a) threads and (b)
> event-driven programming. GLib is an example of (b), and it really
> does remove the error-prone issues of lock management, concurrent data
> access, and deadlocks from the equation. In return, you get to make
> sure you clean up your event handlers when you're not using them :)
> You can add as many timeout_add_seconds() as you like, or you can put
> most of your logic into the one. Globals will work precisely because
> you aren't doing multiple threads and thus you are sure that there is
> only one thing accessing the global data at a given time. But globals
> have their downsides too (mainly from a readability and refactor-
> ability perspective).
> There's always the signals option too, if you want to go fully event-
> driven. They have nothing to do with the mainloop BTW. But they also
> break up the program flow and if you have long chains of them, it can
> become a bit more confusing.
> But back to your original question, here's an example of getting NM
> state too:
> #!/usr/bin/env python
> import gi
> gi.require_version('ModemManager', '1.0')
> gi.require_version('NM', '1.0')
> from gi.repository import GLib, GObject, Gio, ModemManager, NM
> import sys, signal
> main_loop = None
> def signal_handler(data):
>  main_loop.quit()
> def get_modem_state(data):
>  (obj, nm) = data
>  modem = obj.get_modem()
>  print "Modem State: %s" % ModemManager.ModemState.get_string(modem.get_state())
> print "NM state: %s" % nm.get_nm_running()
> # Do whatever other work you need to do, as long as it doesn't take many seconds
> # True = continue running this timeout
>  return True
> main_loop = GLib.MainLoop()
> GLib.unix_signal_add(GLib.PRIORITY_HIGH, signal.SIGHUP, signal_handler, None)
> GLib.unix_signal_add(GLib.PRIORITY_HIGH, signal.SIGTERM, signal_handler, None)
> connection = Gio.bus_get_sync(Gio.BusType.SYSTEM, None)
> manager = ModemManager.Manager.new_sync(connection,
>  Gio.DBusObjectManagerClientFlags.DO_NOT_AUTO_START,
>  None)
> modems = manager.get_objects()
> if len(modems) == 0:
>  print "no modems found"
>  sys.exit(1)
> nm =
> GLib.timeout_add_seconds(5, get_modem_state, (modems[0], nm))
> try:
> except KeyboardInterrupt:
>  pass

Thanks Dan. I've persevered with GLib, and made a bit of progress.
On top of your suggestion - instead of the start-up "modems = manager.get_objects()" etc, I've hooked in [a derivation of] the ModemWatcher example, and pass an instance in the timeout_add_seconds() instead of 'modems[0]'.
Getting somewhere under normal circumstances, but I've found that if MM is restarted whilst the script is running, then get_modem_state() no longer gets called at all. The ModemWatcher instance *is* still spotting the presence of the modem, even if I unload its driver after stopping MM and reload it after MM is restarted.
Something, I guess, has got unhooked in the event driving...?

More information about the ModemManager-devel mailing list