OK, two problems.
Problem number one seems to have been introduced with the LocalSocket option. 
In fact, that config value is ignored in favor of its key, the literal 
"LocalSocket". So the plugin creates the socket as "LocalSocket", connects to 
the pdns control socket and sends the data. When the pdns control socket 
attempts to send data back, it finds no socket called "LocalSocket" as it's in 
a different working directory.  Of course, this shouldn't cause collectd to 
hang. That's the second problem. The plugin's socket has no recv timeout. 
Since it was able to connect and send data successfully, it waits indefinitely 
for a response that's not coming.

Both problems are fixed in the attached patch, which I made against the squeeze 
debian source. I've tested the resulting package successfully in a lenny 
environment, both with and without a chrooted pdns_recursor.

Luke Heberling
--- collectd-4.6.3.broken/src/powerdns.c	2009-06-02 02:17:47.000000000 -0700
+++ collectd-4.6.3/src/powerdns.c	2009-07-27 16:44:32.000000000 -0700
@@ -380,6 +380,16 @@ static int powerdns_get_data_dgram (list
       break;
     }
 
+    struct timeval timeout;
+    timeout.tv_sec=5;
+    timeout.tv_usec=0;
+    status = setsockopt (sd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof (timeout));
+    if (status != 0)
+    {
+      FUNC_ERROR ("setsockopt");
+      break;
+    }
+
     status = connect (sd, (struct sockaddr *) &item->sockaddr,
         sizeof (item->sockaddr));
     if (status != 0)
@@ -911,11 +921,18 @@ static int powerdns_config (oconfig_item
       powerdns_config_add_server (option);
     else if (strcasecmp ("LocalSocket", option->key) == 0)
     {
-      char *temp = strdup (option->key);
-      if (temp == NULL)
-        return (1);
-      sfree (local_sockpath);
-      local_sockpath = temp;
+      if ((option->values_num != 1) || (option->values[0].type != OCONFIG_TYPE_STRING))
+      {
+        WARNING ("powerdns plugin: `%s' needs exactly one string argument.", ci->key);
+      }
+      else
+      {
+        char *temp = strdup (option->values[0].value.string);
+        if (temp == NULL)
+          return (1);
+        sfree (local_sockpath);
+        local_sockpath = temp;
+      }
     }
     else
     {

Reply via email to