Hi Sebastian

Sebastian Harl wrote:
>> Hmm, is there a chance having collectd running multiple times using the
>> same socket file?
> 
> Well, yes -- if it's misconfigured … ;-)

heh, ok. great :)


>>> At the very least (imho), we should check if that file is a UNIX socket,
>>> and possibly (I'm not sure if that's possible [in a portable way]) check
>>> if the socket is not in use. If both of that is the case, we can be
>>> fairly sure that removing the file is safe.
>> Ok, i understand. That makes sense.
> 
> Are you willing to give that a try and provide a patch?

Sure..

The attached patch handles stale socket files and removes only if it is
a socket and it is not possible to connect() to it. Code is borrowed
from clamav :)

I'm not sure if the stat check is portable enough (manual says it is not
in POSIX.1-1996).

kind regards,
peter

-- 
:: e n d i a n
:: open source - open minds

:: peter warasin
:: http://www.endian.com   :: [email protected]
This patch handles failure to bind to a unix socket

If the bind fails because of "address already in use",
file will be stat()'ed in order to check if it is a socket.
If it is and it is not possible to connect to, it is assumed
that no process is using it, so the socket file is
considered stale and will be removed.

In all other cases it will bailed out with a corresponding
message.

---
 src/unixsock.c |   53 +++++++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 47 insertions(+), 6 deletions(-)

Index: collectd-4.9.1/src/unixsock.c
===================================================================
--- collectd-4.9.1.orig/src/unixsock.c	2010-03-24 17:48:02.000000000 +0100
+++ collectd-4.9.1/src/unixsock.c	2010-03-24 18:40:22.000000000 +0100
@@ -89,7 +89,6 @@
 	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);
 
@@ -97,11 +96,53 @@
 	if (status != 0)
 	{
 		char errbuf[1024];
-		sstrerror (errno, errbuf, sizeof (errbuf));
-		ERROR ("unixsock plugin: bind failed: %s", errbuf);
-		close (sock_fd);
-		sock_fd = -1;
-		return (-1);
+		struct stat statbuf;
+
+		if (errno != EADDRINUSE)
+		{
+		  sstrerror (errno, errbuf, sizeof (errbuf));
+		  ERROR ("unixsock plugin: bind failed: %s", errbuf);
+		  close (sock_fd);
+		  sock_fd = -1;
+		  return (-1);
+		}
+		if (stat(sa.sun_path, &statbuf) == 0)
+		{
+		  if ((statbuf.st_mode & S_IFMT) != S_IFSOCK)
+		  {
+		    ERROR ("unixsock plugin: File %s is in the way. "
+			   "Either remove it or configure a different socket file.", sa.sun_path);
+		    close (sock_fd);
+		    sock_fd = -1;
+		    return (-1);
+		  }
+		}
+		if (connect(sock_fd, (struct sockaddr *) &sa,
+			    sizeof(struct sockaddr_un)) >= 0)
+		{
+		  ERROR ("unixsock plugin: Socket file %s is in use by another process.", sa.sun_path);
+		  close (sock_fd);
+		  sock_fd = -1;
+		  return (-1);
+		}
+		WARNING ("unixsock plugin: Removing stale socket file %s", sa.sun_path);
+		if (unlink(sa.sun_path) == -1)
+		{
+		  sstrerror (errno, errbuf, sizeof (errbuf));
+		  ERROR ("unixsock plugin: Could not remove socket file %s", sa.sun_path);
+		  close (sock_fd);
+		  sock_fd = -1;
+		  return (-1);
+		}
+		status = bind (sock_fd, (struct sockaddr *) &sa, sizeof (sa));
+		if (status != 0)
+		{
+		  sstrerror (errno, errbuf, sizeof (errbuf));
+		  ERROR ("unixsock plugin: bind failed after unlink stale socket: %s", errbuf);
+		  close (sock_fd);
+		  sock_fd = -1;
+		  return (-1);
+		}
 	}
 
 	chmod (sa.sun_path, sock_perms);
_______________________________________________
collectd mailing list
[email protected]
http://mailman.verplant.org/listinfo/collectd

Reply via email to