Code

Merge remote-tracking branch 'github/pr/387'
[collectd.git] / src / unixsock.c
index 57f34501f8f0dfd423c4c1c8435ea71e9caaf2bc..2c1665fc9fcbbdffc3c91935838a720e4fbf6d6f 100644 (file)
@@ -53,7 +53,8 @@ static const char *config_keys[] =
 {
        "SocketFile",
        "SocketGroup",
-       "SocketPerms"
+       "SocketPerms",
+       "DeleteSocket"
 };
 static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
 
@@ -64,6 +65,7 @@ static int   sock_fd    = -1;
 static char *sock_file  = NULL;
 static char *sock_group = NULL;
 static int   sock_perms = S_IRWXU | S_IRWXG;
+static _Bool delete_socket = 0;
 
 static pthread_t listen_thread = (pthread_t) 0;
 
@@ -88,10 +90,27 @@ static int us_open_socket (void)
        sa.sun_family = AF_UNIX;
        sstrncpy (sa.sun_path, (sock_file != NULL) ? sock_file : US_DEFAULT_PATH,
                        sizeof (sa.sun_path));
-       /* unlink (sa.sun_path); */
 
        DEBUG ("unixsock plugin: socket path = %s", sa.sun_path);
 
+       if (delete_socket)
+       {
+               errno = 0;
+               status = unlink (sa.sun_path);
+               if ((status != 0) && (errno != ENOENT))
+               {
+                       char errbuf[1024];
+                       WARNING ("unixsock plugin: Deleting socket file \"%s\" failed: %s",
+                                       sa.sun_path,
+                                       sstrerror (errno, errbuf, sizeof (errbuf)));
+               }
+               else if (status == 0)
+               {
+                       INFO ("unixsock plugin: Successfully deleted socket file \"%s\".",
+                                       sa.sun_path);
+               }
+       }
+
        status = bind (sock_fd, (struct sockaddr *) &sa, sizeof (sa));
        if (status != 0)
        {
@@ -157,33 +176,48 @@ static int us_open_socket (void)
 
 static void *us_handle_client (void *arg)
 {
-       int fd;
+       int fdin;
+       int fdout;
        FILE *fhin, *fhout;
 
-       fd = *((int *) arg);
+       fdin = *((int *) arg);
        free (arg);
        arg = NULL;
 
-       DEBUG ("unixsock plugin: us_handle_client: Reading from fd #%i", fd);
+       DEBUG ("unixsock plugin: us_handle_client: Reading from fd #%i", fdin);
+
+       fdout = dup (fdin);
+       if (fdout < 0)
+       {
+               char errbuf[1024];
+               ERROR ("unixsock plugin: dup failed: %s",
+                               sstrerror (errno, errbuf, sizeof (errbuf)));
+               close (fdin);
+               pthread_exit ((void *) 1);
+       }
 
-       fhin  = fdopen (fd, "r");
+       fhin  = fdopen (fdin, "r");
        if (fhin == NULL)
        {
                char errbuf[1024];
                ERROR ("unixsock plugin: fdopen failed: %s",
                                sstrerror (errno, errbuf, sizeof (errbuf)));
-               close (fd);
+               close (fdin);
+               close (fdout);
                pthread_exit ((void *) 1);
+               return ((void *) 1);
        }
 
-       fhout = fdopen (fd, "w");
+       fhout = fdopen (fdout, "w");
        if (fhout == NULL)
        {
                char errbuf[1024];
                ERROR ("unixsock plugin: fdopen failed: %s",
                                sstrerror (errno, errbuf, sizeof (errbuf)));
-               fclose (fhin); /* this closes fd as well */
+               fclose (fhin); /* this closes fdin as well */
+               close (fdout);
                pthread_exit ((void *) 1);
+               return ((void *) 1);
        }
 
        /* change output buffer to line buffered mode */
@@ -195,6 +229,7 @@ static void *us_handle_client (void *arg)
                fclose (fhin);
                fclose (fhout);
                pthread_exit ((void *) 1);
+               return ((void *) 0);
        }
 
        while (42)
@@ -208,6 +243,9 @@ static void *us_handle_client (void *arg)
                errno = 0;
                if (fgets (buffer, sizeof (buffer), fhin) == NULL)
                {
+                       if ((errno == EINTR) || (errno == EAGAIN))
+                               continue;
+
                        if (errno != 0)
                        {
                                char errbuf[1024];
@@ -230,11 +268,13 @@ static void *us_handle_client (void *arg)
 
                fields_num = strsplit (buffer_copy, fields,
                                sizeof (fields) / sizeof (fields[0]));
-
                if (fields_num < 1)
                {
-                       close (fd);
-                       break;
+                       fprintf (fhout, "-1 Internal error\n");
+                       fclose (fhin);
+                       fclose (fhout);
+                       pthread_exit ((void *) 1);
+                       return ((void *) 1);
                }
 
                if (strcasecmp (fields[0], "getval") == 0)
@@ -285,6 +325,9 @@ static void *us_server_thread (void __attribute__((unused)) *arg)
        pthread_t th;
        pthread_attr_t th_attr;
 
+       pthread_attr_init (&th_attr);
+       pthread_attr_setdetachstate (&th_attr, PTHREAD_CREATE_DETACHED);
+
        if (us_open_socket () != 0)
                pthread_exit ((void *) 1);
 
@@ -303,6 +346,7 @@ static void *us_server_thread (void __attribute__((unused)) *arg)
                                        sstrerror (errno, errbuf, sizeof (errbuf)));
                        close (sock_fd);
                        sock_fd = -1;
+                       pthread_attr_destroy (&th_attr);
                        pthread_exit ((void *) 1);
                }
 
@@ -319,10 +363,8 @@ static void *us_server_thread (void __attribute__((unused)) *arg)
 
                DEBUG ("Spawning child to handle connection on fd #%i", *remote_fd);
 
-               pthread_attr_init (&th_attr);
-               pthread_attr_setdetachstate (&th_attr, PTHREAD_CREATE_DETACHED);
-
-               status = pthread_create (&th, &th_attr, us_handle_client, (void *) remote_fd);
+               status = plugin_thread_create (&th, &th_attr,
+                               us_handle_client, (void *) remote_fd);
                if (status != 0)
                {
                        char errbuf[1024];
@@ -336,6 +378,7 @@ static void *us_server_thread (void __attribute__((unused)) *arg)
 
        close (sock_fd);
        sock_fd = -1;
+       pthread_attr_destroy (&th_attr);
 
        status = unlink ((sock_file != NULL) ? sock_file : US_DEFAULT_PATH);
        if (status != 0)
@@ -373,6 +416,13 @@ static int us_config (const char *key, const char *val)
        {
                sock_perms = (int) strtol (val, NULL, 8);
        }
+       else if (strcasecmp (key, "DeleteSocket") == 0)
+       {
+               if (IS_TRUE (val))
+                       delete_socket = 1;
+               else
+                       delete_socket = 0;
+       }
        else
        {
                return (-1);
@@ -394,7 +444,8 @@ static int us_init (void)
 
        loop = 1;
 
-       status = pthread_create (&listen_thread, NULL, us_server_thread, NULL);
+       status = plugin_thread_create (&listen_thread, NULL,
+                       us_server_thread, NULL);
        if (status != 0)
        {
                char errbuf[1024];