linux-hotplug.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Chris Friesen <chris_friesen@sympatico.ca>
To: linux-hotplug@vger.kernel.org
Subject: [PATCH] convert udevsend/udevd to using datagram sockets
Date: Wed, 04 Feb 2004 07:00:35 +0000	[thread overview]
Message-ID: <40209893.8080109@sympatico.ca> (raw)

[-- Attachment #1: Type: text/plain, Size: 1083 bytes --]

This patch does a couple of things to udevsend/udevd.  It doesn't touch
udev itself at all.

1) It switches to using the abstract namespace.  This simplifies things
since you don't have to go around unlinking.  When the socket goes away,
the address is gone.

2) The protocol between udevsend and udevd is fundamentally
message-based.  This patch recognizes this by using SOCK_DGRAM rather
than SOCK_STREAM, which simplifies the message protocol.  (Note that
with unix sockets, you can still detect if the daemon is not running
with SOCK_DGRAM. )

3) The main loop in udevd is much simplified.  Part of this is due to
the lower complexity of datagram sockets.  As well, the new main loop
just calls a plain function that sits on a blocking recv() to handle
incoming messages instead of spawning a thread that does almost nothing
and then exits.

There is still a hole if the message gets delivered and the server
crashes before it gets handled--to close that we would need an ack
message.  If anyone wants us to be that paranoid, it would be easy to
implement.

Any comments?

Chris

[-- Attachment #2: udev_dgram.patch --]
[-- Type: text/plain, Size: 7303 bytes --]

diff -Nur --exclude=RCS --exclude=CVS --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet udev/Makefile myudev/Makefile
--- udev/Makefile	Tue Feb  3 19:50:35 2004
+++ myudev/Makefile	Wed Feb  4 00:43:18 2004
@@ -241,7 +241,6 @@
 	@echo \#define UDEV_PERMISSION_FILE	\"$(configdir)\udev.permissions\" >> $@
 	@echo \#define UDEV_BIN		\"$(DESTDIR)$(sbindir)/udev\" >> $@
 	@echo \#define UDEVD_BIN	\"$(DESTDIR)$(sbindir)/udevd\" >> $@
-	@echo \#define UDEVD_SOCK	\"$(udevdir)/\.udevd.sock\" >> $@
 	@echo \#define UDEVD_LOCK	\"$(udevdir)/\.udevd.lock\" >> $@
 
 # config files automatically generated
diff -Nur --exclude=RCS --exclude=CVS --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet udev/udevd.c myudev/udevd.c
--- udev/udevd.c	Tue Feb  3 19:50:45 2004
+++ myudev/udevd.c	Wed Feb  4 01:18:12 2004
@@ -272,39 +272,32 @@
 }
 
 /* every connect creates a thread which gets the msg, queues it and exits */
-static void *client_threads(void * parm)
+static void client_threads(int sock)
 {
-	int sock;
 	struct hotplug_msg *msg;
 	int retval;
 
-	sock = (int) parm;
-
 	msg = msg_create();
 	if (msg == NULL) {
 		dbg("unable to store message");
-		goto exit;
+		return;
 	}
 
 	retval = recv(sock, msg, sizeof(struct hotplug_msg), 0);
 	if (retval <  0) {
 		dbg("unable to receive message");
-		goto exit;
+		return;
 	}
 
 	if (strncmp(msg->magic, UDEV_MAGIC, sizeof(UDEV_MAGIC)) != 0 ) {
 		dbg("message magic '%s' doesn't match, ignore it", msg->magic);
 		msg_delete(msg);
-		goto exit;
+		return;
 	}
 
 	pthread_mutex_lock(&msg_lock);
 	msg_queue_insert(msg);
 	pthread_mutex_unlock(&msg_lock);
-
-exit:
-	close(sock);
-	pthread_exit(0);
 }
 
 static void sig_handler(int signum)
@@ -313,7 +306,6 @@
 		case SIGINT:
 		case SIGTERM:
 			unlink(UDEVD_LOCK);
-			unlink(UDEVD_SOCK);
 			exit(20 + signum);
 			break;
 		default:
@@ -346,14 +338,11 @@
 int main(int argc, char *argv[])
 {
 	int ssock;
-	int csock;
 	struct sockaddr_un saddr;
-	struct sockaddr_un caddr;
-	socklen_t clen;
-	pthread_t cli_tid;
 	pthread_t mgr_msg_tid;
 	pthread_t mgr_exec_tid;
 	int retval;
+	int addrlen;
 
 	init_logging("udevd");
 
@@ -366,27 +355,26 @@
 
 	memset(&saddr, 0x00, sizeof(saddr));
 	saddr.sun_family = AF_LOCAL;
-	strcpy(saddr.sun_path, UDEVD_SOCK);
+   saddr.sun_path[0] = 0;
+   strcpy(saddr.sun_path+1, UDEV_SOCK_NAME);
+	
+   /* The size of the address is the offset of the start of the filename,
+    * plus its length, plus one for the beginning null byte.
+	 */
+   addrlen = offsetof(struct sockaddr_un, sun_path) + strlen (saddr.sun_path+1) + 1;
 
-	unlink(UDEVD_SOCK);
-	ssock = socket(AF_LOCAL, SOCK_STREAM, 0);
+	ssock = socket(AF_LOCAL, SOCK_DGRAM, 0);
 	if (ssock == -1) {
 		dbg("error getting socket");
 		exit(1);
 	}
 
-	retval = bind(ssock, &saddr, sizeof(saddr));
+	retval = bind(ssock, &saddr, addrlen);
 	if (retval < 0) {
 		dbg("bind failed\n");
 		goto exit;
 	}
 
-	retval = listen(ssock, SOMAXCONN);
-	if (retval < 0) {
-		dbg("listen failed\n");
-		goto exit;
-	}
-
 	pthread_mutex_init(&msg_lock, NULL);
 	pthread_mutex_init(&msg_active_lock, NULL);
 	pthread_mutex_init(&exec_lock, NULL);
@@ -402,18 +390,12 @@
 	pthread_create(&mgr_msg_tid, &thr_attr, msg_queue_manager, NULL);
 	pthread_create(&mgr_exec_tid, &thr_attr, exec_queue_manager, NULL);
 
-	clen = sizeof(caddr);
 	/* main loop */
 	while (1) {
-		csock = accept(ssock, &caddr, &clen);
-		if (csock < 0) {
-			dbg("client accept failed\n");
-			continue;
-		}
-		pthread_create(&cli_tid, &thr_attr, client_threads, (void *) csock);
+
+		client_threads(ssock);
 	}
 exit:
 	close(ssock);
-	unlink(UDEVD_SOCK);
 	exit(1);
 }
diff -Nur --exclude=RCS --exclude=CVS --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet udev/udevd.h myudev/udevd.h
--- udev/udevd.h	Wed Feb  4 00:34:24 2004
+++ myudev/udevd.h	Wed Feb  4 00:34:55 2004
@@ -24,6 +24,7 @@
 
 #include "list.h"
 
+#define UDEV_SOCK_NAME "udevd"
 #define UDEV_MAGIC			"udevd_" UDEV_VERSION
 #define EVENT_TIMEOUT_SEC		5
 #define UDEVSEND_CONNECT_RETRY		20 /* x 100 millisec */
diff -Nur --exclude=RCS --exclude=CVS --exclude=SCCS --exclude=BitKeeper --exclude=ChangeSet udev/udevsend.c myudev/udevsend.c
--- udev/udevsend.c	Tue Feb  3 19:50:45 2004
+++ myudev/udevsend.c	Wed Feb  4 01:47:25 2004
@@ -32,6 +32,7 @@
 #include <string.h>
 #include <unistd.h>
 #include <time.h>
+#include <linux/stddef.h>
 
 #include "udev.h"
 #include "udev_version.h"
@@ -118,12 +119,14 @@
 	char *subsystem;
 	char *seqnum;
 	int seq;
-	int retval = -EINVAL;
+	int retval=1;
 	int size;
 	int loop;
 	struct timespec tspec;
 	int sock;
 	struct sockaddr_un saddr;
+	int addrlen;
+	int started_daemon = 0;
 
 #ifdef DEBUG
 	init_logging("udevsend");
@@ -154,7 +157,7 @@
 	}
 	seq = atoi(seqnum);
 
-	sock = socket(AF_LOCAL, SOCK_STREAM, 0);
+	sock = socket(AF_LOCAL, SOCK_DGRAM, 0);
 	if (sock == -1) {
 		dbg("error getting socket");
 		goto exit;
@@ -162,50 +165,51 @@
 
 	memset(&saddr, 0x00, sizeof(saddr));
 	saddr.sun_family = AF_LOCAL;
-	strcpy(saddr.sun_path, UDEVD_SOCK);
+	saddr.sun_path[0] = 0;
+	strcpy(saddr.sun_path+1, UDEV_SOCK_NAME);
 
-	/* try to connect, if it fails start daemon */
-	retval = connect(sock, (struct sockaddr *) &saddr, sizeof(saddr));
-	if (retval != -1) {
-		goto send;
-	} else {
-		dbg("connect failed, try starting daemon...");
-		retval = start_daemon();
-		if (retval == 0) {
-			dbg("daemon started");
-		} else {
-			dbg("error starting daemon");
-			goto exit;
-		}
-	}
+	/* The size of the address is the offset of the start of the filename,
+	 * plus its length, plus one for the beginning null byte.
+	 */
+	addrlen = offsetof(struct sockaddr_un, sun_path) + strlen (saddr.sun_path+1) + 1;
+	size = build_hotplugmsg(&message, action, devpath, subsystem, seq);
 
-	/* try to connect while daemon to starts */
-	tspec.tv_sec = 0;
-	tspec.tv_nsec = 100000000;  /* 100 millisec */
+	/* Send to daemon.  If daemon doesn't exist, start it and loop on sending
+	 * while daemon starts.
+	 */
 	loop = UDEVSEND_CONNECT_RETRY;
 	while (loop--) {
-		retval = connect(sock, (struct sockaddr *) &saddr, sizeof(saddr));
-		if (retval != -1)
-			goto send;
-		else
-			dbg("retry to connect %d",
-			    UDEVSEND_CONNECT_RETRY - loop);
-		nanosleep(&tspec, NULL);
-	}
-	dbg("error connecting to daemon, start daemon failed");
-	goto exit;
-
-send:
-	size = build_hotplugmsg(&message, action, devpath, subsystem, seq);
-	retval = send(sock, &message, size, 0);
-	if (retval == -1) {
-		dbg("error sending message");
-		close (sock);
-		goto exit;
+		retval = sendto(sock, &message, size, 0, (struct sockaddr*)&saddr, addrlen);
+		if (retval != -1) {
+			retval = 0;
+			goto close_and_exit;
+		}
+		
+		if (errno != ECONNREFUSED) {
+			dbg("error sending message");
+			goto close_and_exit;
+		}
+		
+		if (!started_daemon) {
+			dbg("connect failed, try starting daemon...");
+			retval = start_daemon();
+			if (retval) {
+				dbg("error starting daemon");
+				goto exit;
+			}
+			
+			dbg("daemon started");
+			started_daemon = 1;
+		} else {
+			dbg("retry to connect %d", UDEVSEND_CONNECT_RETRY - loop);
+			tspec.tv_sec = 0;
+			tspec.tv_nsec = 100000000;  /* 100 millisec */
+			nanosleep(&tspec, NULL);
+		}
 	}
-	close (sock);
-	return 0;
-
+	
+close_and_exit:
+	close(sock);
 exit:
-	return 1;
+	return retval;
 }

             reply	other threads:[~2004-02-04  7:00 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-02-04  7:00 Chris Friesen [this message]
2004-02-04 14:02 ` [PATCH] convert udevsend/udevd to using datagram sockets Kay Sievers
2004-02-04 15:34 ` chris_friesen
2004-02-04 21:06 ` Mike Waychison
2004-02-05  1:24 ` Chris Friesen
2004-02-05  2:08 ` Mike Waychison
2004-02-05  6:53 ` Chris Friesen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=40209893.8080109@sympatico.ca \
    --to=chris_friesen@sympatico.ca \
    --cc=linux-hotplug@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).