USBIP daemon relies on functions available in glib2 library to spawn handler code for incoming connection. This makes the whole program dependent on glib2 library, which is a GNOME library that on systems that don't have GNOME results in pulling more dependency, only to be able to run a relatively trivial socket-based program. While this may not seem to be a problem on full-blown desktops that already have the necessary libraries, it is a big issue on small embedded systems (think USB hub with an Ethernet port) that only have bare essentials in their file systems. This patch eliminates glib2 dependency by reworking the code to use lower level system calls to dispatch connection handler. Instead of using glib2-style event loop and dispatching mechanism, just do a ppoll(2) system call in our own loop and call accept(2) followed by fork(2) on the socket that has incoming connection. Stevens' books taught us that more than twenty years ago. No need for anything smarter in a simple server, such as usbipd. Signed-off-by: Ilija Hadzic <ihadzic@xxxxxxxxxxxxxxxxxxxxxx> --- drivers/staging/usbip/userspace/README | 2 - drivers/staging/usbip/userspace/configure.ac | 5 -- drivers/staging/usbip/userspace/src/Makefile.am | 4 +- drivers/staging/usbip/userspace/src/usbipd.c | 96 ++++++++++++++----------- 4 files changed, 57 insertions(+), 50 deletions(-) diff --git a/drivers/staging/usbip/userspace/README b/drivers/staging/usbip/userspace/README index 63cd107..233d1d7 100644 --- a/drivers/staging/usbip/userspace/README +++ b/drivers/staging/usbip/userspace/README @@ -17,8 +17,6 @@ - gcc >= 4.0 - - libglib2.0-dev >= 2.6.0 - - libtool, automake >= 1.9, autoconf >= 2.5.0, pkg-config diff --git a/drivers/staging/usbip/userspace/configure.ac b/drivers/staging/usbip/userspace/configure.ac index 43e641e..6d52841 100644 --- a/drivers/staging/usbip/userspace/configure.ac +++ b/drivers/staging/usbip/userspace/configure.ac @@ -91,10 +91,5 @@ AC_ARG_WITH([usbids-dir], [USBIDS_DIR=$withval], [USBIDS_DIR="/usr/share/hwdata/"]) AC_SUBST([USBIDS_DIR]) -GLIB2_REQUIRED=2.6.0 -PKG_CHECK_MODULES([PACKAGE], [glib-2.0 >= $GLIB2_REQUIRED]) -AC_SUBST([PACKAGE_CFLAGS]) -AC_SUBST([PACKAGE_LIBS]) - AC_CONFIG_FILES([Makefile libsrc/Makefile src/Makefile]) AC_OUTPUT diff --git a/drivers/staging/usbip/userspace/src/Makefile.am b/drivers/staging/usbip/userspace/src/Makefile.am index c365a3f..a113003 100644 --- a/drivers/staging/usbip/userspace/src/Makefile.am +++ b/drivers/staging/usbip/userspace/src/Makefile.am @@ -1,6 +1,6 @@ AM_CPPFLAGS = -I$(top_srcdir)/libsrc -DUSBIDS_FILE='"@USBIDS_DIR@/usb.ids"' -AM_CFLAGS = @EXTRA_CFLAGS@ @PACKAGE_CFLAGS@ -LDADD = $(top_builddir)/libsrc/libusbip.la @PACKAGE_LIBS@ +AM_CFLAGS = @EXTRA_CFLAGS@ +LDADD = $(top_builddir)/libsrc/libusbip.la sbin_PROGRAMS := usbip usbipd diff --git a/drivers/staging/usbip/userspace/src/usbipd.c b/drivers/staging/usbip/userspace/src/usbipd.c index 8668a80..34760cc 100644 --- a/drivers/staging/usbip/userspace/src/usbipd.c +++ b/drivers/staging/usbip/userspace/src/usbipd.c @@ -20,6 +20,7 @@ #include "../config.h" #endif +#define _GNU_SOURCE #include <errno.h> #include <unistd.h> #include <netdb.h> @@ -35,10 +36,9 @@ #include <tcpd.h> #endif -#define _GNU_SOURCE #include <getopt.h> -#include <glib.h> #include <signal.h> +#include <poll.h> #include "usbip_host_driver.h" #include "usbip_common.h" @@ -48,7 +48,7 @@ #define PROGNAME "usbipd" #define MAXSOCKFD 20 -GMainLoop *main_loop; +#define MAIN_LOOP_TIMEOUT 10 static const char usbip_version_string[] = PACKAGE_STRING; @@ -310,30 +310,22 @@ static int do_accept(int listenfd) return connfd; } -gboolean process_request(GIOChannel *gio, GIOCondition condition, - gpointer unused_data) +int process_request(int listenfd) { - int listenfd; + pid_t childpid; int connfd; - (void) unused_data; - - if (condition & (G_IO_ERR | G_IO_HUP | G_IO_NVAL)) { - err("unknown condition"); - BUG(); - } - - if (condition & G_IO_IN) { - listenfd = g_io_channel_unix_get_fd(gio); - connfd = do_accept(listenfd); - if (connfd < 0) - return TRUE; - + connfd = do_accept(listenfd); + if (connfd < 0) + return -1; + childpid = fork(); + if (childpid == 0) { + close(listenfd); recv_pdu(connfd); - close(connfd); + exit(0); } - - return TRUE; + close(connfd); + return 0; } static void log_addrinfo(struct addrinfo *ai) @@ -418,10 +410,7 @@ static struct addrinfo *do_getaddrinfo(char *host, int ai_family) static void signal_handler(int i) { - dbg("received signal: code %d", i); - - if (main_loop) - g_main_loop_quit(main_loop); + dbg("received '%s' signal", strsignal(i)); } static void set_signal(void) @@ -433,14 +422,19 @@ static void set_signal(void) sigemptyset(&act.sa_mask); sigaction(SIGTERM, &act, NULL); sigaction(SIGINT, &act, NULL); + act.sa_handler = SIG_IGN; + sigaction(SIGCLD, &act, NULL); } -static int do_standalone_mode(gboolean daemonize) +static int do_standalone_mode(int daemonize) { struct addrinfo *ai_head; int sockfdlist[MAXSOCKFD]; int nsockfd; - int i; + int i, terminate; + struct pollfd *fds; + struct timespec timeout; + sigset_t sigmask; if (usbip_names_init(USBIDS_FILE)) err("failed to open %s", USBIDS_FILE); @@ -456,7 +450,7 @@ static int do_standalone_mode(gboolean daemonize) err("daemonizing failed: %s", strerror(errno)); return -1; } - + umask(0); usbip_use_syslog = 1; } set_signal(); @@ -472,20 +466,40 @@ static int do_standalone_mode(gboolean daemonize) err("failed to open a listening socket"); return -1; } - + fds = calloc(nsockfd, sizeof(struct pollfd)); for (i = 0; i < nsockfd; i++) { - GIOChannel *gio; - - gio = g_io_channel_unix_new(sockfdlist[i]); - g_io_add_watch(gio, (G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL), - process_request, NULL); + fds[i].fd = sockfdlist[i]; + fds[i].events = POLLIN; + } + timeout.tv_sec = MAIN_LOOP_TIMEOUT; + timeout.tv_nsec = 0; + + sigfillset(&sigmask); + sigdelset(&sigmask, SIGTERM); + sigdelset(&sigmask, SIGINT); + + terminate = 0; + while (!terminate) { + int r; + + r = ppoll(fds, nsockfd, &timeout, &sigmask); + if (r < 0) { + dbg("%s", strerror(errno)); + terminate = 1; + } else if (r) { + for (i = 0; i < nsockfd; i++) { + if (fds[i].revents & POLLIN) { + dbg("read event on fd[%d]=%d", + i, sockfdlist[i]); + process_request(sockfdlist[i]); + } + } + } else + dbg("heartbeat timeout on ppoll()"); } - - main_loop = g_main_loop_new(FALSE, FALSE); - g_main_loop_run(main_loop); info("shutting down " PROGNAME); - + free(fds); freeaddrinfo(ai_head); usbip_host_driver_close(); usbip_names_free(); @@ -509,7 +523,7 @@ int main(int argc, char *argv[]) cmd_version } cmd; - gboolean daemonize = FALSE; + int daemonize = 0; int opt, rc = -1; usbip_use_stderr = 1; @@ -527,7 +541,7 @@ int main(int argc, char *argv[]) switch (opt) { case 'D': - daemonize = TRUE; + daemonize = 1; break; case 'd': usbip_use_debug = 1; -- 1.7.12 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html