linux-hotplug.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Kay Sievers <kay.sievers@vrfy.org>
To: linux-hotplug@vger.kernel.org
Subject: Re: udev and dbus
Date: Fri, 12 Mar 2004 15:54:24 +0000	[thread overview]
Message-ID: <20040312155424.GA3530@vrfy.org> (raw)
In-Reply-To: <20040217214449.GB12411@wonderland.linux.it>

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

On Fri, Mar 12, 2004 at 12:37:05PM +0100, David Zeuthen wrote:
> > I think the dbus people need to work on their "issues" a bit first
> > before we go and start changing udev.  Sound ok?
> > 
> 
> What we're really arguing about is where projects higher in the stack
> than udev (like hal) should place their scripts. I'm saying /etc/udev.d
> and Kay is saying /etc/hotplug.d. FWIW, I can live with both proposals,
> though I think it's conceptually clearer to use /etc/udev.d. But let's
> not dicsuss the merits of these proposals again.

Here is my proposed version. :) 
udevsend is changed to wait until the real udev comes back from
execution by udevd. udevsend now returns the exit code of udev itself.

If udevsend is the first program executed by /sbin/hotplug, by introducing
a folder in /etc/hotplug.d/ in which to look first, or something similar,
all following programs are executed after the device nodes are created.
Which seems very nice, not only for a dbus-script. And we keep _all_
scripts in /etc/hotplug.d/.

Any script, like the dbus-sender can easily get any value from udev's db,
with udevinfo:


  #!/bin/sh
  if [ "$ACTION" = "add" ]; then
          NODE=`udevinfo -q name -p $DEVPATH`
          logger "node=${NODE}"
  fi
  exit 0


The patch for udevsend/udevd is attached. It's based on Chris Friesen's
"ack msg" patch.

thanks,
Kay

[-- Attachment #2: 90-udevsend-wait.patch --]
[-- Type: text/plain, Size: 6847 bytes --]

===== udevd.c 1.23 vs edited =====
--- 1.23/udevd.c	Wed Mar  3 22:05:10 2004
+++ edited/udevd.c	Fri Mar 12 15:49:10 2004
@@ -222,6 +222,15 @@
 	}
 }
 
+static void send_ack_msg(int sock, struct hotplug_msg *msg)
+{
+	int retval;
+	dbg("sending ack msg for seq %i", msg->seqnum);
+	retval = sendto(sock, msg, sizeof(struct hotplug_msg), 0, (struct sockaddr*) &msg->addr, msg->addrlen);
+	if (retval == -1)
+		dbg("error sending ack msg");
+}
+
 /* receive the msg, do some basic sanity checks, and queue it */
 static void handle_msg(int sock)
 {
@@ -232,6 +241,7 @@
 	struct iovec iov;
 	struct ucred *cred;
 	char cred_msg[CMSG_SPACE(sizeof(struct ucred))];
+	struct sockaddr_un addr;
 
 	msg = msg_create();
 	if (msg == NULL) {
@@ -247,29 +257,39 @@
 	smsg.msg_iovlen = 1;
 	smsg.msg_control = cred_msg;
 	smsg.msg_controllen = sizeof(cred_msg);
+	smsg.msg_name = &addr;
+	smsg.msg_namelen = sizeof(addr);
 
 	retval = recvmsg(sock, &smsg, 0);
 	if (retval <  0) {
 		if (errno != EINTR)
 			dbg("unable to receive message");
-		return;
+		goto skip;
 	}
+
+	if (retval != sizeof(struct hotplug_msg)) {
+		dbg("wrong message size");
+		goto skip;
+	}
+
 	cmsg = CMSG_FIRSTHDR(&smsg);
 	cred = (struct ucred *) CMSG_DATA(cmsg);
+	memcpy(&msg->addr, smsg.msg_name, smsg.msg_namelen);
+	msg->addrlen = smsg.msg_namelen;
+
+	if (strncmp(msg->magic, UDEV_MAGIC, sizeof(UDEV_MAGIC)) != 0 ) {
+		dbg("message magic '%s' doesn't match, ignore it", msg->magic);
+		goto skip;
+	}
 
 	if (cmsg == NULL || cmsg->cmsg_type != SCM_CREDENTIALS) {
 		dbg("no sender credentials received, message ignored");
-		goto skip;
+		goto refuse;
 	}
 
 	if (cred->uid != 0) {
 		dbg("sender uid=%i, message ignored", cred->uid);
-		goto skip;
-	}
-
-	if (strncmp(msg->magic, UDEV_MAGIC, sizeof(UDEV_MAGIC)) != 0 ) {
-		dbg("message magic '%s' doesn't match, ignore it", msg->magic);
-		goto skip;
+		goto refuse;
 	}
 
 	/* if no seqnum is given, we move straight to exec queue */
@@ -281,6 +301,10 @@
 	}
 	return;
 
+refuse:
+	msg->rc = EMSG_REFUSED;
+	send_ack_msg(sock, msg);
+
 skip:
 	free(msg);
 	return;
@@ -304,7 +328,7 @@
 	}
 }
 
-static void udev_done(int pid)
+static void udev_done(int pid, int rc, int sock)
 {
 	/* find msg associated with pid and delete it */
 	struct hotplug_msg *msg;
@@ -312,6 +336,9 @@
 	list_for_each_entry(msg, &running_list, list) {
 		if (msg->pid == pid) {
 			dbg("<== exec seq %d came back", msg->seqnum);
+			msg->rc = rc;
+			send_ack_msg(sock, msg);
+
 			run_queue_delete(msg);
 			return;
 		}
@@ -326,6 +353,8 @@
 	int retval;
 	const int on = 1;
 	struct sigaction act;
+	int status;
+	int rc;
 
 	init_logging("udevd");
 	dbg("version %s", UDEV_VERSION);
@@ -381,10 +410,16 @@
 			children_waiting = 0;
 			/* reap all dead children */
 			while(1) {
-				int pid = waitpid(-1, 0, WNOHANG);
+				int pid = waitpid(-1, &status, WNOHANG);
 				if ((pid == -1) || (pid == 0))
 					break;
-				udev_done(pid);
+
+				if (WIFEXITED(status))
+					rc = WEXITSTATUS(status);
+				else
+					rc = 0;
+
+				udev_done(pid, rc, ssock);
 			}
 		}
 	}
===== udevd.h 1.8 vs edited =====
--- 1.8/udevd.h	Thu Feb 26 04:09:18 2004
+++ edited/udevd.h	Fri Mar 12 16:09:17 2004
@@ -25,16 +25,26 @@
 #include "list.h"
 
 #define UDEV_MAGIC			"udevd_" UDEV_VERSION
-#define EVENT_TIMEOUT_SEC		5
 #define UDEVSEND_CONNECT_RETRY		20 /* x 100 millisec */
 #define UDEVD_SOCK_PATH			"udevd"
 
+#define EVENT_TIMEOUT_SEC		5
+#define ACK_TIMEOUT_SEC			(EVENT_TIMEOUT_SEC + 5)
+
+#define ETIMEOUT_RCV_ACK		16
+#define EMSG_REFUSED			17
+#define EMSG_SEND			18
+
+
 struct hotplug_msg {
-	char magic[20];
 	struct list_head list;
 	pid_t pid;
-	int seqnum;
 	time_t queue_time;
+	struct sockaddr_un addr;
+	socklen_t addrlen;
+	char magic[20];
+	int seqnum;
+	int rc;
 	char action[ACTION_SIZE];
 	char devpath[DEVPATH_SIZE];
 	char subsystem[SUBSYSTEM_SIZE];
===== udevsend.c 1.27 vs edited =====
--- 1.27/udevsend.c	Wed Mar  3 22:07:05 2004
+++ edited/udevsend.c	Fri Mar 12 16:05:43 2004
@@ -22,6 +22,7 @@
  *
  */
 
+#include <sys/select.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/wait.h>
@@ -95,6 +96,7 @@
 	default:
 		wait(NULL);
 	}
+
 	return 0;
 }
 
@@ -106,7 +108,7 @@
 	char *subsystem;
 	char *seqnum;
 	int seq;
-	int retval = 1;
+	int retval;
 	int size;
 	int loop;
 	struct timespec tspec;
@@ -114,6 +116,7 @@
 	struct sockaddr_un saddr;
 	socklen_t addrlen;
 	int started_daemon = 0;
+	int rc = EMSG_SEND;
 
 #ifdef DEBUG
 	init_logging("udevsend");
@@ -156,6 +159,14 @@
 
 	memset(&saddr, 0x00, sizeof(saddr));
 	saddr.sun_family = AF_LOCAL;
+	sprintf(&saddr.sun_path[1], "%d", getpid());
+	addrlen = offsetof(struct sockaddr_un, sun_path) + strlen(saddr.sun_path+1) + 1;
+	
+	if (bind(sock, (struct sockaddr*)&saddr, addrlen) < 0) {
+		dbg("error binding socket");
+		goto exit;
+	}
+		
 	/* use abstract namespace for socket path */
 	strcpy(&saddr.sun_path[1], UDEVD_SOCK_PATH);
 	addrlen = offsetof(struct sockaddr_un, sun_path) + strlen(saddr.sun_path+1) + 1;
@@ -164,11 +175,54 @@
 
 	/* If we can't send, try to start daemon and resend message */
 	loop = UDEVSEND_CONNECT_RETRY;
+
 	while (loop--) {
+		dbg("sending message for seq %i", msg.seqnum);
 		retval = sendto(sock, &msg, size, 0, (struct sockaddr *)&saddr, addrlen);
 		if (retval != -1) {
-			retval = 0;
-			goto close_and_exit;
+			/* wait for ack */
+			fd_set rdset;
+			int count;
+			struct timeval tv = {ACK_TIMEOUT_SEC, 0};
+
+			while(1) {
+				FD_ZERO(&rdset);
+				FD_SET(sock, &rdset);
+				count = select(sock+1, &rdset, NULL, NULL, &tv);
+				if (count == 0) {
+					dbg("timeout waiting for ack msg");
+					rc = ETIMEOUT_RCV_ACK;
+					goto close_and_exit;
+					
+				}
+
+				if (FD_ISSET(sock, &rdset)) {
+					struct hotplug_msg ack;
+
+					retval = recv(sock, &ack, sizeof(ack), MSG_DONTWAIT);
+					if (retval <= 0) {
+						dbg("no ack msg received");
+						continue;
+					}
+
+					if (strncmp(ack.magic, msg.magic, sizeof(UDEV_MAGIC)) != 0 ) {
+						dbg("wrong ack msg magic '%s'", ack.magic);
+						continue;
+					}
+
+					if (ack.rc == EMSG_REFUSED) {
+						dbg("seq %i is refused", ack.seqnum);
+						rc = EMSG_REFUSED;
+						goto close_and_exit;
+					}
+
+					if (ack.seqnum == msg.seqnum) {
+						dbg("seq %i returned with %i", ack.seqnum, ack.rc);
+						rc = ack.rc;
+						goto close_and_exit;
+					}
+				}
+			}
 		}
 		
 		if (errno != ECONNREFUSED) {
@@ -179,11 +233,10 @@
 		if (!started_daemon) {
 			dbg("connect failed, try starting daemon...");
 			retval = start_daemon();
-			if (retval) {
+			if (retval != 0) {
 				dbg("error starting daemon");
 				goto exit;
 			}
-			
 			dbg("daemon started");
 			started_daemon = 1;
 		} else {
@@ -193,9 +246,9 @@
 			nanosleep(&tspec, NULL);
 		}
 	}
-	
+
 close_and_exit:
 	close(sock);
 exit:
-	return retval;
+	return rc;
 }

  parent reply	other threads:[~2004-03-12 15:54 UTC|newest]

Thread overview: 44+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-02-17 21:44 udev and DBUS Marco d'Itri
2004-02-26 17:00 ` Marco d'Itri
2004-02-28 14:13 ` David Zeuthen
2004-03-10 16:31 ` udev and dbus David Zeuthen
2004-03-10 17:52 ` Kay Sievers
2004-03-10 19:18 ` Greg KH
2004-03-10 19:56 ` Greg KH
2004-03-10 19:57 ` Marco d'Itri
2004-03-10 20:00 ` Marco d'Itri
2004-03-10 20:02 ` Greg KH
2004-03-10 22:25 ` Patrick Mansfield
2004-03-10 22:37 ` Kay Sievers
2004-03-10 22:48 ` Greg KH
2004-03-11  1:28 ` Greg KH
2004-03-11  2:35 ` Kay Sievers
2004-03-11  8:55 ` Martin Waitz
2004-03-11 14:30 ` Kay Sievers
2004-03-11 15:06 ` David Zeuthen
2004-03-11 17:14 ` Kay Sievers
2004-03-11 17:23 ` Kay Sievers
2004-03-11 17:30 ` David Zeuthen
2004-03-11 17:41 ` David Zeuthen
2004-03-11 17:44 ` Kay Sievers
2004-03-11 18:12 ` Kay Sievers
2004-03-11 18:22 ` David Zeuthen
2004-03-11 18:32 ` Greg KH
2004-03-11 18:35 ` Greg KH
2004-03-11 18:36 ` Greg KH
2004-03-11 18:37 ` Kay Sievers
2004-03-11 18:38 ` Kay Sievers
2004-03-11 18:40 ` Kay Sievers
2004-03-11 18:47 ` Greg KH
2004-03-11 18:56 ` Kay Sievers
2004-03-12  0:18 ` Greg KH
2004-03-12 11:37 ` David Zeuthen
2004-03-12 15:54 ` Kay Sievers [this message]
2004-03-12 16:40 ` Daniel Stekloff
2004-03-12 17:17 ` Marco d'Itri
2004-03-12 17:26 ` Marco d'Itri
2004-03-13 15:22 ` David Zeuthen
2004-03-13 18:29 ` Kay Sievers
2004-03-14 19:59 ` Olaf Hering
2004-03-14 20:06 ` Kay Sievers
2004-03-14 20:11 ` Olaf Hering

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=20040312155424.GA3530@vrfy.org \
    --to=kay.sievers@vrfy.org \
    --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).