gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r36065 - in gnunet: doc/man src/arm src/include src/util


From: gnunet
Subject: [GNUnet-SVN] r36065 - in gnunet: doc/man src/arm src/include src/util
Date: Mon, 13 Jul 2015 16:53:30 +0200

Author: grothoff
Date: 2015-07-13 16:53:30 +0200 (Mon, 13 Jul 2015)
New Revision: 36065

Modified:
   gnunet/doc/man/gnunet.conf.5
   gnunet/src/arm/gnunet-service-arm.c
   gnunet/src/include/gnunet_network_lib.h
   gnunet/src/util/network.c
Log:
automatically clean up left-over Unix domain socket files when trying to bind 
(fixes #3723)

Modified: gnunet/doc/man/gnunet.conf.5
===================================================================
--- gnunet/doc/man/gnunet.conf.5        2015-07-13 14:07:08 UTC (rev 36064)
+++ gnunet/doc/man/gnunet.conf.5        2015-07-13 14:53:30 UTC (rev 36065)
@@ -28,6 +28,10 @@
     Start the service always when the peer starts.  Set to YES for services 
that should always be launched, even if no other service explicitly needs them.
 .IP AUTOSTART
     Set to YES to automatically start the service when it is requested by 
another service. YES for most GNUnet services.
+.IP NOARMBIND
+    Set to YES to never have ARM bind to the respective socket. This option is 
mostly for debugging in situations where ARM cannot pass the pre-bound socket 
to the child due to interference from PREFIX-commands.  This option is only 
effective in combination with FORCESTART being YES.  NO by default.
+.IP PREFIX
+    PREFIX the given command (with its arguments) to the actual BINARY to be 
executed. Useful to run certain services under special supervisors (like strace 
or valgrind).  Typically used in combination with FORCESTART and NOARMBIND. 
Empty by default.
 .IP ACCEPT_FROM
     A semi-column separated list of IPv4 addresses that are allowed to use the 
service; usually 127.0.0.1.
 .IP ACCEPT_FROM6

Modified: gnunet/src/arm/gnunet-service-arm.c
===================================================================
--- gnunet/src/arm/gnunet-service-arm.c 2015-07-13 14:07:08 UTC (rev 36064)
+++ gnunet/src/arm/gnunet-service-arm.c 2015-07-13 14:53:30 UTC (rev 36065)
@@ -603,7 +603,8 @@
  * @param sl service entry for the service in question
  */
 static void
-create_listen_socket (struct sockaddr *sa, socklen_t addr_len,
+create_listen_socket (struct sockaddr *sa,
+                      socklen_t addr_len,
                      struct ServiceList *sl)
 {
   static int on = 1;
@@ -652,14 +653,18 @@
     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
                         "setsockopt");
 #endif
-
+#ifndef WINDOWS
+  if (AF_UNIX == sa->sa_family)
+    GNUNET_NETWORK_unix_precheck ((struct sockaddr_un *) sa);
+#endif
   if (GNUNET_OK !=
       GNUNET_NETWORK_socket_bind (sock, (const struct sockaddr *) sa, 
addr_len))
   {
     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                _
-                ("Unable to bind listening socket for service `%s' to address 
`%s': %s\n"),
-                sl->name, GNUNET_a2s (sa, addr_len), STRERROR (errno));
+                _("Unable to bind listening socket for service `%s' to address 
`%s': %s\n"),
+                sl->name,
+                GNUNET_a2s (sa, addr_len),
+                STRERROR (errno));
     GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock));
     GNUNET_free (sa);
     return;
@@ -1394,11 +1399,11 @@
                                             "FORCESTART"))
   {
     sl->force_start = GNUNET_YES;
-    /* FIXME: we might like the pre-binding even for
-       _certain_ services that have force_start set,
-       otherwise interdependencies may again force
-       client's to retry connections during startup. */
-    return;
+    if (GNUNET_YES ==
+        GNUNET_CONFIGURATION_get_value_yesno (cfg,
+                                              section,
+                                              "NOARMBIND"))
+      return;
   }
   else
   {

Modified: gnunet/src/include/gnunet_network_lib.h
===================================================================
--- gnunet/src/include/gnunet_network_lib.h     2015-07-13 14:07:08 UTC (rev 
36064)
+++ gnunet/src/include/gnunet_network_lib.h     2015-07-13 14:53:30 UTC (rev 
36065)
@@ -106,7 +106,22 @@
 GNUNET_NETWORK_shorten_unixpath (char *unixpath);
 
 
+#ifndef WINDOWS
 /**
+ * If services crash, they can leave a unix domain socket file on the
+ * disk. This needs to be manually removed, because otherwise both
+ * bind() and connect() for the respective address will fail.  In this
+ * function, we test if such a left-over file exists, and if so,
+ * remove it (unless there is a listening service at the address).
+ *
+ * @param un unix domain socket address to check
+ */
+void
+GNUNET_NETWORK_unix_precheck (const struct sockaddr_un *un);
+#endif
+
+
+/**
  * Accept a new connection on a socket.  Configure it for non-blocking
  * IO and mark it as non-inheritable to child processes (set the
  * close-on-exec flag).

Modified: gnunet/src/util/network.c
===================================================================
--- gnunet/src/util/network.c   2015-07-13 14:07:08 UTC (rev 36064)
+++ gnunet/src/util/network.c   2015-07-13 14:53:30 UTC (rev 36065)
@@ -147,6 +147,53 @@
 }
 
 
+#ifndef WINDOWS
+/**
+ * If services crash, they can leave a unix domain socket file on the
+ * disk. This needs to be manually removed, because otherwise both
+ * bind() and connect() for the respective address will fail.  In this
+ * function, we test if such a left-over file exists, and if so,
+ * remove it (unless there is a listening service at the address).
+ *
+ * @param un unix domain socket address to check
+ */
+void
+GNUNET_NETWORK_unix_precheck (const struct sockaddr_un *un)
+{
+  int s;
+  int eno;
+  struct stat sbuf;
+  int ret;
+
+  s = socket (AF_UNIX, SOCK_STREAM, 0);
+  ret = connect (s,
+                 (struct sockaddr *) un,
+                 sizeof (struct sockaddr_un));
+  eno = errno;
+  GNUNET_break (0 == close (s));
+  if (0 == ret)
+    return; /* another process is listening, do not remove! */
+  if (ECONNREFUSED != eno)
+    return; /* some other error, likely "no such file or directory" -- all 
well */
+  /* should unlink, but sanity checks first */
+  if (0 != stat (un->sun_path,
+                 &sbuf))
+    return; /* failed to 'stat', likely does not exist after all */
+  if (S_IFSOCK != (S_IFMT & sbuf.st_mode))
+    return; /* refuse to unlink anything except sockets */
+  /* finally, really unlink */
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+              "Removing left-over `%s' from previous exeuction\n",
+              un->sun_path);
+  if (0 != unlink (un->sun_path))
+    GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
+                              "unlink",
+                              un->sun_path);
+}
+#endif
+
+
+
 #ifndef FD_COPY
 #define FD_COPY(s, d) (memcpy ((d), (s), sizeof (fd_set)))
 #endif
@@ -447,6 +494,8 @@
 #endif
 #endif
 #ifndef WINDOWS
+  if (AF_UNIX == address->sa_family)
+    GNUNET_NETWORK_unix_precheck ((const struct sockaddr_un *) address);
   {
     const int on = 1;
 
@@ -459,8 +508,6 @@
       LOG_STRERROR (GNUNET_ERROR_TYPE_DEBUG,
                     "setsockopt");
   }
-#endif
-#ifndef WINDOWS
   {
     /* set permissions of newly created non-abstract UNIX domain socket to
        "user-only"; applications can choose to relax this later */
@@ -476,7 +523,10 @@
       old_mask = umask (S_IWGRP | S_IRGRP | S_IXGRP | S_IWOTH | S_IROTH | 
S_IXOTH);
 #endif
 
-    ret = bind (desc->fd, address, address_len);
+    ret = bind (desc->fd,
+                address,
+                address_len);
+
 #ifndef WINDOWS
     if (not_abstract)
       (void) umask (old_mask);
@@ -486,7 +536,7 @@
   if (SOCKET_ERROR == ret)
     SetErrnoFromWinsockError (WSAGetLastError ());
 #endif
-  if (ret != 0)
+  if (0 != ret)
     return GNUNET_SYSERR;
 #ifndef MINGW
   desc->addr = GNUNET_malloc (address_len);




reply via email to

[Prev in Thread] Current Thread [Next in Thread]