Commit 328f7f8a authored by Ilija Hadzic's avatar Ilija Hadzic Committed by Greg Kroah-Hartman

staging: usbip: userspace: eliminate glib dependency

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: default avatarIlija Hadzic <ihadzic@research.bell-labs.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 0d0651d4
...@@ -17,8 +17,6 @@ ...@@ -17,8 +17,6 @@
- gcc >= 4.0 - gcc >= 4.0
- libglib2.0-dev >= 2.6.0
- libtool, automake >= 1.9, autoconf >= 2.5.0, pkg-config - libtool, automake >= 1.9, autoconf >= 2.5.0, pkg-config
......
...@@ -91,10 +91,5 @@ AC_ARG_WITH([usbids-dir], ...@@ -91,10 +91,5 @@ AC_ARG_WITH([usbids-dir],
[USBIDS_DIR=$withval], [USBIDS_DIR="/usr/share/hwdata/"]) [USBIDS_DIR=$withval], [USBIDS_DIR="/usr/share/hwdata/"])
AC_SUBST([USBIDS_DIR]) 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_CONFIG_FILES([Makefile libsrc/Makefile src/Makefile])
AC_OUTPUT AC_OUTPUT
AM_CPPFLAGS = -I$(top_srcdir)/libsrc -DUSBIDS_FILE='"@USBIDS_DIR@/usb.ids"' AM_CPPFLAGS = -I$(top_srcdir)/libsrc -DUSBIDS_FILE='"@USBIDS_DIR@/usb.ids"'
AM_CFLAGS = @EXTRA_CFLAGS@ @PACKAGE_CFLAGS@ AM_CFLAGS = @EXTRA_CFLAGS@
LDADD = $(top_builddir)/libsrc/libusbip.la @PACKAGE_LIBS@ LDADD = $(top_builddir)/libsrc/libusbip.la
sbin_PROGRAMS := usbip usbipd sbin_PROGRAMS := usbip usbipd
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include "../config.h" #include "../config.h"
#endif #endif
#define _GNU_SOURCE
#include <errno.h> #include <errno.h>
#include <unistd.h> #include <unistd.h>
#include <netdb.h> #include <netdb.h>
...@@ -35,10 +36,9 @@ ...@@ -35,10 +36,9 @@
#include <tcpd.h> #include <tcpd.h>
#endif #endif
#define _GNU_SOURCE
#include <getopt.h> #include <getopt.h>
#include <glib.h>
#include <signal.h> #include <signal.h>
#include <poll.h>
#include "usbip_host_driver.h" #include "usbip_host_driver.h"
#include "usbip_common.h" #include "usbip_common.h"
...@@ -48,7 +48,7 @@ ...@@ -48,7 +48,7 @@
#define PROGNAME "usbipd" #define PROGNAME "usbipd"
#define MAXSOCKFD 20 #define MAXSOCKFD 20
GMainLoop *main_loop; #define MAIN_LOOP_TIMEOUT 10
static const char usbip_version_string[] = PACKAGE_STRING; static const char usbip_version_string[] = PACKAGE_STRING;
...@@ -310,30 +310,22 @@ static int do_accept(int listenfd) ...@@ -310,30 +310,22 @@ static int do_accept(int listenfd)
return connfd; return connfd;
} }
gboolean process_request(GIOChannel *gio, GIOCondition condition, int process_request(int listenfd)
gpointer unused_data)
{ {
int listenfd; pid_t childpid;
int connfd; int connfd;
(void) unused_data; connfd = do_accept(listenfd);
if (connfd < 0)
if (condition & (G_IO_ERR | G_IO_HUP | G_IO_NVAL)) { return -1;
err("unknown condition"); childpid = fork();
BUG(); if (childpid == 0) {
} close(listenfd);
if (condition & G_IO_IN) {
listenfd = g_io_channel_unix_get_fd(gio);
connfd = do_accept(listenfd);
if (connfd < 0)
return TRUE;
recv_pdu(connfd); recv_pdu(connfd);
close(connfd); exit(0);
} }
close(connfd);
return TRUE; return 0;
} }
static void log_addrinfo(struct addrinfo *ai) static void log_addrinfo(struct addrinfo *ai)
...@@ -418,10 +410,7 @@ static struct addrinfo *do_getaddrinfo(char *host, int ai_family) ...@@ -418,10 +410,7 @@ static struct addrinfo *do_getaddrinfo(char *host, int ai_family)
static void signal_handler(int i) static void signal_handler(int i)
{ {
dbg("received signal: code %d", i); dbg("received '%s' signal", strsignal(i));
if (main_loop)
g_main_loop_quit(main_loop);
} }
static void set_signal(void) static void set_signal(void)
...@@ -433,14 +422,19 @@ static void set_signal(void) ...@@ -433,14 +422,19 @@ static void set_signal(void)
sigemptyset(&act.sa_mask); sigemptyset(&act.sa_mask);
sigaction(SIGTERM, &act, NULL); sigaction(SIGTERM, &act, NULL);
sigaction(SIGINT, &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; struct addrinfo *ai_head;
int sockfdlist[MAXSOCKFD]; int sockfdlist[MAXSOCKFD];
int nsockfd; int nsockfd;
int i; int i, terminate;
struct pollfd *fds;
struct timespec timeout;
sigset_t sigmask;
if (usbip_names_init(USBIDS_FILE)) if (usbip_names_init(USBIDS_FILE))
err("failed to open %s", USBIDS_FILE); err("failed to open %s", USBIDS_FILE);
...@@ -456,7 +450,7 @@ static int do_standalone_mode(gboolean daemonize) ...@@ -456,7 +450,7 @@ static int do_standalone_mode(gboolean daemonize)
err("daemonizing failed: %s", strerror(errno)); err("daemonizing failed: %s", strerror(errno));
return -1; return -1;
} }
umask(0);
usbip_use_syslog = 1; usbip_use_syslog = 1;
} }
set_signal(); set_signal();
...@@ -472,20 +466,40 @@ static int do_standalone_mode(gboolean daemonize) ...@@ -472,20 +466,40 @@ static int do_standalone_mode(gboolean daemonize)
err("failed to open a listening socket"); err("failed to open a listening socket");
return -1; return -1;
} }
fds = calloc(nsockfd, sizeof(struct pollfd));
for (i = 0; i < nsockfd; i++) { for (i = 0; i < nsockfd; i++) {
GIOChannel *gio; fds[i].fd = sockfdlist[i];
fds[i].events = POLLIN;
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), timeout.tv_sec = MAIN_LOOP_TIMEOUT;
process_request, NULL); 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); info("shutting down " PROGNAME);
free(fds);
freeaddrinfo(ai_head); freeaddrinfo(ai_head);
usbip_host_driver_close(); usbip_host_driver_close();
usbip_names_free(); usbip_names_free();
...@@ -509,7 +523,7 @@ int main(int argc, char *argv[]) ...@@ -509,7 +523,7 @@ int main(int argc, char *argv[])
cmd_version cmd_version
} cmd; } cmd;
gboolean daemonize = FALSE; int daemonize = 0;
int opt, rc = -1; int opt, rc = -1;
usbip_use_stderr = 1; usbip_use_stderr = 1;
...@@ -527,7 +541,7 @@ int main(int argc, char *argv[]) ...@@ -527,7 +541,7 @@ int main(int argc, char *argv[])
switch (opt) { switch (opt) {
case 'D': case 'D':
daemonize = TRUE; daemonize = 1;
break; break;
case 'd': case 'd':
usbip_use_debug = 1; usbip_use_debug = 1;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment