[gnet-dev] Unlinking, take 2



Patch attached against current CVS.

No longer exports gnet_unix_socket_unlink().

gnet_unix_socket_delete() now destroys socket, ignoring reference count.

gnet_unix_socket_unref() now calls _delete() if necessary.

gnet_unix_socket_server_new() now calls _unlink() before bind(), and
calls _delete() on error.

examples/echoserver-unix.c has been updated to use _delete() instead of
unlink().

And comments have been updated to improve their gtk-docness.

M
diff -urNb gnet/examples/echoserver-unix.c gnet-unix/examples/echoserver-unix.c
--- gnet/examples/echoserver-unix.c	Tue Oct 23 07:46:19 2001
+++ gnet-unix/examples/echoserver-unix.c	Thu Oct 25 14:58:28 2001
@@ -21,7 +21,6 @@
 #include <stdlib.h>
 #include <string.h>
 #include <sys/types.h>
-#include <sys/stat.h>
 #include <unistd.h>
 #include <signal.h>
 #include <glib.h>
@@ -36,14 +35,13 @@
 static void normal_echoserver(gchar *path);
 static void async_echoserver(gchar *path);
 
-gchar *socket_path;
+GUnixSocket *server;
 
 int
 main(int argc, char** argv)
 {
   gchar *path = NULL;
   ServerType server_type = NORMAL;
-  struct stat stbuf;
 	
   if (argc !=  2 && argc != 3) {
     usage(EXIT_FAILURE);
@@ -59,16 +57,6 @@
   path = g_new0(gchar, strlen(argv[argc - 1]));
   path = memcpy(path, argv[argc - 1], strlen(argv[argc - 1]));
 
-  if (stat(path, &stbuf) == 0) {
-    if (S_ISSOCK(stbuf.st_mode)) {
-      unlink(path);
-    } else {
-      g_print("%s is not a socket!\n", path);
-      exit(EXIT_FAILURE);
-    }
-  }
-  socket_path = path;
-
   signal(SIGINT, cleanup_on_sig);
   signal(SIGTERM, cleanup_on_sig);
 		
@@ -97,19 +85,13 @@
 void
 cleanup_on_sig(int signum)
 {
-  struct stat stbuf;
-  if (stat(socket_path, &stbuf) == 0) {
-    if (S_ISSOCK(stbuf.st_mode)) {
-      unlink(socket_path);
-    }
-  }
+  gnet_unix_socket_delete(server);
   exit(EXIT_SUCCESS);
 }
 
 static void
 normal_echoserver(gchar *path)
 {
-  GUnixSocket *server;
   GUnixSocket *client = NULL;
   gchar buffer[1024];
   guint n;
@@ -172,7 +154,6 @@
 static void
 async_echoserver(gchar *path)
 {
-  GUnixSocket *server;
   GIOChannel *iochannel = NULL;
   GMainLoop *main_loop = NULL;
 
diff -urNb gnet/src/unix.c gnet-unix/src/unix.c
--- gnet/src/unix.c	Tue Oct 23 07:46:20 2001
+++ gnet-unix/src/unix.c	Thu Oct 25 14:55:20 2001
@@ -22,18 +22,18 @@
 #include "unix.h"
 
 #define PATH(S) (((struct sockaddr_un *) (&(S)->sa))->sun_path)
-
+gboolean gnet_unix_socket_unlink(gchar *path);
 
 /**
  *  gnet_unix_socket_connect:
  *  @path: Path to socket to connect to
  *
- *  A quick and easy GUnixSocket constructor.  This connects to the
+ *  A quick and easy #GUnixSocket constructor.  This connects to the
  *  specified path.  This function does block.  Use this function when
  *  you are a client connecting to a server and you don't mind
  *  blocking.
  *
- *  Returns: A new GUnixSocket, or NULL if there was a failure.  
+ *  Returns: A new #GUnixSocket, or NULL if there was a failure.  
  *
  **/
 GUnixSocket *
@@ -46,11 +46,11 @@
  *  gnet_unix_socket_new:
  *  @path: Path to connect to.
  *
- *  Connect to a specified address.  use this sort of socket when
+ *  Connect to a specified address.  Use this sort of socket when
  *  you're a client connecting to a server.  This function will block
  *  to connect.
  *
- *  Returns a new GUnixSocket, or NULL if there was a failure.
+ *  Returns: A new #GUnixSocket, or NULL if there was a failure.
  *
  **/
 GUnixSocket *
@@ -83,21 +83,27 @@
  *  gnet_unix_socket_delete:
  *  @s: UnixSocket to delete.
  *
- *  Close and delete a GUnixSocket.
+ *  Close and delete a #GUnixSocket, regardless of reference count.
  *
  **/
 void
 gnet_unix_socket_delete(GUnixSocket *s)
 {
-  if (s != NULL)
-    gnet_unix_socket_unref(s);
+  g_return_if_fail(s != NULL);
+  
+  GNET_CLOSE_SOCKET(s->sockfd); /* Don't care if this fails. */
+  if (s->iochannel)
+    g_io_channel_unref(s->iochannel);
+  if (s->server)
+    gnet_unix_socket_unlink(PATH(s));
+  g_free(s);
 }
 
 /**
  *  gnet_unix_socket_ref
  *  @s: GUnixSocket to reference
  *
- *  Increment the reference counter of the GUnixSocket.
+ *  Increment the reference counter of a #GUnixSocket.
  *
  **/
 void
@@ -111,7 +117,7 @@
  *  gnet_unix_socket_unref
  *  @s: GUnixSocket to unreference
  *
- *  Remove a reference from the GUnixSocket.  When the reference count
+ *  Remove a reference from the #GUnixSocket.  When the reference count
  *  reaches 0, the socket is deleted.  
  *
  **/
@@ -121,38 +127,20 @@
   g_return_if_fail(s != NULL);
 
   --s->ref_count;
-
   if (s->ref_count == 0) 
-    {
-      GNET_CLOSE_SOCKET(s->sockfd); /* Don't care if this fails */
-      if (s->iochannel)
-	g_io_channel_unref(s->iochannel);
-      if (s->server) 
-	{
-	  struct stat buf;
-	  if (stat(PATH(s), &buf) == 0) 
-	    {
-	      if (S_ISSOCK(buf.st_mode)) 
-		{
-		  /* FIXME */
-		  unlink(PATH(s));
-		}
-	    }
-	} 
-      g_free(s);
-    }
+    gnet_unix_socket_delete(s);
 }
     
 /**
  *  gnet_unix_socket_get_iochannel
  *  @socket: GUnixSocket to get GIOChannel from.
  *
- *  Get the GIOChannel for the GUnixSocket.
+ *  Get the #GIOChannel for the #GUnixSocket.
  *
- *  For a client socket, the GIOChannel represents the data stream.
- *  Use it like you would any other GIOChannel.
+ *  For a client socket, the #GIOChannel represents the data stream.
+ *  Use it like you would any other #GIOChannel.
  *
- *  For a server socket, however, the GIOChannel represents incoming
+ *  For a server socket, however, the #GIOChannel represents incoming
  *  connections.  If you can read from it, there's a connection
  *  waiting to be accepted.
  *
@@ -161,7 +149,7 @@
  *  you are done with it.  However, you should not close the channel -
  *  this is done when you delete the socket.
  *
- *  Returns: A GIOChannel; NULL on failure.  
+ *  Returns: A #GIOChannel; NULL on failure.  
  *
  **/
 GIOChannel*
@@ -197,10 +185,10 @@
  *  gnet_unix_socket_server_new:
  *  @path: Path for the socket.
  *
- *  Create and open a new GUnixSocket with the specified path.  Use *
+ *  Create and open a new #GUnixSocket with the specified path.  Use
  *  this sort of socket when you are a server.
  *
- *  Returns: a new GUnixSocket, or NULL if there was a failure.  
+ *  Returns: a new #GUnixSocket, or NULL if there was a failure.  
  *
  **/
 GUnixSocket*
@@ -219,6 +207,10 @@
   memcpy(sa_un->sun_path, path, strlen(path));
   s->ref_count = 1;
   s->server = TRUE;
+  
+  if (! gnet_unix_socket_unlink(PATH(s)))
+    goto error;
+  
   s->sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
   if (s->sockfd < 0)
     goto error;
@@ -245,7 +237,7 @@
 	
  error:
   if (s)
-    g_free(s);
+    gnet_unix_socket_delete(s);
   return NULL;
 }
 
@@ -255,12 +247,12 @@
  *  @socket: GUnixSocket to accept connections from
  *
  *  Accept connections from the socket.  The socket must have been
- *  created using gnet_unix_socket_server_new(); This function will
+ *  created using gnet_unix_socket_server_new(). This function will
  *  block (use gnet_unix_socket_server_accept_nonblock() if you don't
- *  want to block).  If the socket's GIOChannel is readable, it DOES
+ *  want to block).  If the socket's #GIOChannel is readable, it DOES
  *  NOT mean that this function will block.
  *
- *  Returns: a new GUnixSocket if there is another connect, or NULL if
+ *  Returns: a new #GUnixSocket if there is another connect, or NULL if
  *  there's an error.  
  *
  **/
@@ -309,12 +301,12 @@
  *
  *  Accept a connection from the socket without blocking.  The socket
  *  must have been created using gnet_unix_socket_server_new().  This
- *  function is best used with the sockets GIOChannel.  If the channel
+ *  function is best used with the socket's #GIOChannel.  If the channel
  *  is readable, then you PROBABLY have a connection.  It is possible
  *  for the connection to close by the time you call this, so it may
  *  return NULL even if the channel was readable.
  *
- *  Returns: a new GUnixSocket if there was another connect, or NULL
+ *  Returns: a new #GUnixSocket if there was another connect, or NULL
  *  otherwise. 
  *
  **/
@@ -355,4 +347,41 @@
   memcpy(&s->sa, &sa, sizeof(s->sa));
 
   return s;
+}
+
+
+/**
+ *  gnet_unix_socket_unlink:
+ *  @path: Path to socket to unlink.
+ *
+ *  Verifies that the file at the end of the path is a socket, and then
+ *  unlinks it.
+ *
+ *  Returns: TRUE on success, FALSE on failure.
+ **/
+gboolean
+gnet_unix_socket_unlink(gchar *path)
+{
+	struct stat stbuf;
+	int r;
+
+	g_return_val_if_fail(path != NULL, FALSE);
+	r = stat(path, &stbuf);
+	if (r == 0) {
+		if (S_ISSOCK(stbuf.st_mode)) {
+			if (unlink(path) == 0) {
+				return TRUE;
+			} else {
+				/* Can't unlink */
+				return FALSE;
+			}
+		} else {
+			/* path is not a socket */
+			return FALSE;
+		}
+	} else if (errno == ENOENT) {
+		/* File doesn't exist, so we're okay */
+		return TRUE;
+	}
+	return FALSE;
 }


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