From mboxrd@z Thu Jan 1 00:00:00 1970 From: Chris Friesen Date: Wed, 04 Feb 2004 07:00:35 +0000 Subject: [PATCH] convert udevsend/udevd to using datagram sockets Message-Id: <40209893.8080109@sympatico.ca> MIME-Version: 1 Content-Type: multipart/mixed; boundary="------------010001060004010604090409" List-Id: To: linux-hotplug@vger.kernel.org This is a multi-part message in MIME format. --------------010001060004010604090409 Content-Type: text/plain; charset=us-ascii; format=flowed Content-Transfer-Encoding: 7bit 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 --------------010001060004010604090409 Content-Type: text/plain; name="udev_dgram.patch" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="udev_dgram.patch" 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 #include #include +#include #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; } --------------010001060004010604090409-- ------------------------------------------------------- The SF.Net email is sponsored by EclipseCon 2004 Premiere Conference on Open Tools Development and Integration See the breadth of Eclipse activity. February 3-5 in Anaheim, CA. http://www.eclipsecon.org/osdn _______________________________________________ Linux-hotplug-devel mailing list http://linux-hotplug.sourceforge.net Linux-hotplug-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-hotplug-devel