Skip to content

Instantly share code, notes, and snippets.

@jirihnidek
Created May 29, 2017 12:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jirihnidek/4759643a12abcd5d39f41d9d206512d5 to your computer and use it in GitHub Desktop.
Save jirihnidek/4759643a12abcd5d39f41d9d206512d5 to your computer and use it in GitHub Desktop.
Example of reseting resolver using D-Bus, NetworkManager and ctypes
from __future__ import print_function
import dbus
import dbus.mainloop.glib
from gi.repository import GLib
import threading
import time
import socket
import ctypes
try:
from gi.repository import GObject
except ImportError:
import gobject as GObject
def reset_resolver():
"""Attempt to reset the system hostname resolver.
returns 0 on success, or -1 if an error occurs."""
try:
resolv = ctypes.CDLL("libc.so.6")
r = resolv.__res_init()
except (OSError, AttributeError) as err:
print("Could not find __res_init in libc.so.6: %s" % err)
r = -1
return r
NM_STATE_UNKNOWN = 0
NM_STATE_ASLEEP = 10
NM_STATE_DISCONNECTED = 20
NM_STATE_DISCONNECTING = 30
NM_STATE_CONNECTING = 40
NM_STATE_CONNECTED_LOCAL = 50
NM_STATE_CONNECTED_SITE = 60
NM_STATE_CONNECTED_GLOBAL = 70
RESOLVER_RESETTING_STATES = (
NM_STATE_DISCONNECTED,
NM_STATE_CONNECTED_LOCAL,
NM_STATE_CONNECTED_SITE,
NM_STATE_CONNECTED_GLOBAL
)
def signal_handler(*args, **kargs):
"""Handler for D-Bus signal"""
print(args)
for arg in args:
if arg in (RESOLVER_RESETTING_STATES):
reset_resolver()
def nm_check_status(run_event, dbus_loop):
print("Starting thread ...")
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
system_bus = dbus.SystemBus()
system_bus.add_signal_receiver(signal_handler,
dbus_interface="org.freedesktop.NetworkManager",
signal_name="StateChanged")
try:
dbus_loop.run()
except (KeyboardInterrupt, SystemExit):
dbus_loop.quit()
run_event.clear()
print('KeyboardInterrupt 1')
def main():
run_event = threading.Event()
run_event.set()
dbus_loop = GLib.MainLoop()
nm_thread = threading.Thread(target=nm_check_status,
name="NMCheckStatus",
args=(run_event, dbus_loop,))
nm_thread.daemon = True
nm_thread.start()
GObject.threads_init()
while run_event.is_set():
try:
addr = socket.getaddrinfo('redhat.com', '80')
except socket.gaierror as err:
print('Error: %s' % err)
else:
print(addr)
time.sleep(5)
dbus_loop.quit()
nm_thread.join()
if __name__ == '__main__':
main()
@jirihnidek
Copy link
Author

When you will run this code example at Linux machine and you will be connecting and disconnecting this machine from network, then you will see, that this application will be possible to reload new information from /etc/resolv.conf using ctypes, glibc, and res_init() function. When new information is loaded from /etc/resolv.conf, then socket.getaddrinfo() can do resolving without need to restart application.

This is useful mostly for GUI application running for long time period.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment