stuff
[oweals/gnunet.git] / src / util / connection.c
index c572d02de71427d09a8c089555dec50bd9aac814..a877e06c2dcde6f6acaaf3e60d15f82babd9a524 100644 (file)
@@ -279,8 +279,27 @@ struct GNUNET_CONNECTION_Handle
    */
   uint16_t port;
 
+  /**
+   * When shutdown, do not ever actually close the socket, but
+   * free resources.  Only should ever be set if using program
+   * termination as a signal (because only then will the leaked
+   * socket be freed!)
+   */
+  int persist;
+
 };
 
+/**
+ * Set the persist option on this connection handle.  Indicates
+ * that the underlying socket or fd should never really be closed.
+ * Used for indicating process death.
+ *
+ * @param sock the connection to set persistent
+ */
+void GNUNET_CONNECTION_persist_(struct GNUNET_CONNECTION_Handle *sock)
+{
+  sock->persist = GNUNET_YES;
+}
 
 /**
  * Create a socket handle by boxing an existing OS socket.  The OS
@@ -486,7 +505,8 @@ destroy_continuation (void *cls,
       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                   "Shutting down socket (%p)\n", sock);
 #endif
-      GNUNET_NETWORK_socket_shutdown (sock->sock, SHUT_RDWR);
+      if (sock->persist != GNUNET_YES)
+        GNUNET_NETWORK_socket_shutdown (sock->sock, SHUT_RDWR);
     }
   if (sock->read_task != GNUNET_SCHEDULER_NO_TASK)
     {
@@ -518,8 +538,15 @@ destroy_continuation (void *cls,
       sock->nth.notify_ready = NULL;
       notify (sock->nth.notify_ready_cls, 0, NULL);
     }
-  if (sock->sock != NULL)
-    GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock->sock));
+
+  if (sock->sock != NULL) 
+    {
+      if (sock->persist != GNUNET_YES)
+       GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock->sock));
+      else
+       GNUNET_free (sock->sock); /* at least no memory leak (we deliberately
+                                    leak the socket in this special case) ... */
+    }
   GNUNET_free_non_null (sock->addr);
   GNUNET_free_non_null (sock->hostname);
 #if DEBUG_CONNECTION
@@ -931,11 +958,6 @@ void
 GNUNET_CONNECTION_destroy (struct GNUNET_CONNECTION_Handle *sock,
                           int finish_pending_write)
 {
-  if ((sock->write_buffer_off == 0) && (sock->dns_active != NULL))
-    {
-      GNUNET_RESOLVER_request_cancel (sock->dns_active);
-      sock->dns_active = NULL;
-    }
   if (GNUNET_NO == finish_pending_write)
     {
       if (sock->write_task != GNUNET_SCHEDULER_NO_TASK)
@@ -943,8 +965,14 @@ GNUNET_CONNECTION_destroy (struct GNUNET_CONNECTION_Handle *sock,
          GNUNET_SCHEDULER_cancel (sock->sched,
                                   sock->write_task);
          sock->write_task = GNUNET_SCHEDULER_NO_TASK;
+         sock->write_buffer_off = 0;
        }
     }
+  if ((sock->write_buffer_off == 0) && (sock->dns_active != NULL))
+    {
+      GNUNET_RESOLVER_request_cancel (sock->dns_active);
+      sock->dns_active = NULL;
+    }
   GNUNET_assert (sock->sched != NULL);
   GNUNET_SCHEDULER_add_now (sock->sched,
                            &destroy_continuation, sock);
@@ -1538,8 +1566,11 @@ GNUNET_CONNECTION_notify_transmit_ready_cancel (struct
     }
   else
     {
-      GNUNET_SCHEDULER_cancel (h->sh->sched, h->sh->write_task);
-      h->sh->write_task = GNUNET_SCHEDULER_NO_TASK;
+      if (h->sh->write_task != GNUNET_SCHEDULER_NO_TASK)
+       {
+         GNUNET_SCHEDULER_cancel (h->sh->sched, h->sh->write_task);
+         h->sh->write_task = GNUNET_SCHEDULER_NO_TASK;
+       }
     }
   h->notify_ready = NULL;
 }