samba_dnsupdate: make rodc_dns_update() more robust against timing problems
authorStefan Metzmacher <metze@samba.org>
Thu, 7 Feb 2019 08:42:36 +0000 (09:42 +0100)
committerAndrew Bartlett <abartlet@samba.org>
Thu, 14 Feb 2019 01:18:29 +0000 (02:18 +0100)
Without this we had an interesting race!

The messaging_dgm code caches connected datagram sockets based on the
destination pid for 1 second.

The fact that samba_dnsupdate constantly recreates its messaging
context (and the underlying datagram socket) means that we the winbindd
messaging context may get a stale connection. As a result sending any
message from winbindd back to samba_dnsupdate will result in
ECONNREFUSED.

That means the IRPC response from winbindd never reaches
samba_dnsupdate, which will then hit a timeout.

In turn samba_dnsupdate on the RODC times out.

This was a workaround for the problem, by having just one global
IRPC handle and thus just one messaging_dgm context.
The actual problem is solved a few commits before
("messages_dgm: Properly handle receiver re-initialization").
But we keep this as an performance optimization, which hopefully
means that the overall samba_dnsupdate is less likely to
timeout after the hardcoded 20 seconds.

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
source4/scripting/bin/samba_dnsupdate

index 90d4034..3fb540b 100755 (executable)
@@ -633,6 +633,14 @@ def call_samba_tool(d, op="add", zone=None):
             print("Failed 'samba-tool dns' based update: %s : %s" % (str(d), estr))
         raise
 
+irpc_wb = None
+def cached_irpc_wb(lp):
+    global irpc_wb
+    if irpc_wb is not None:
+        return irpc_wb
+    irpc_wb = winbind.winbind("irpc:winbind_server", lp)
+    return irpc_wb
+
 def rodc_dns_update(d, t, op):
     '''a single DNS update via the RODC netlogon call'''
     global sub_vars
@@ -652,7 +660,7 @@ def rodc_dns_update(d, t, op):
         netlogon.NlDnsGenericGcAtSite  : netlogon.NlDnsDomainNameAlias
         }
 
-    w = winbind.winbind("irpc:winbind_server", lp)
+    w = cached_irpc_wb(lp)
     dns_names = netlogon.NL_DNS_NAME_INFO_ARRAY()
     dns_names.count = 1
     name = netlogon.NL_DNS_NAME_INFO()
@@ -680,6 +688,9 @@ def rodc_dns_update(d, t, op):
         print("Error setting DNS entry of type %u: %s: %s" % (t, d, reason))
         error_count = error_count + 1
 
+    if opts.verbose:
+        print("Called netlogon RODC update for %s" % d)
+
     if error_count != 0 and opts.fail_immediately:
         sys.exit(1)