From 7332ad15150acc3224ba97157c0bf90c793661c1 Mon Sep 17 00:00:00 2001 From: pooka Date: Tue, 30 Nov 2010 14:23:24 +0000 Subject: [PATCH] Require server to be explicitly initialized with rump_init_server(url). Also, add rump_daemonize_begin() / rump_daemonize_end() to help with the "can't daemon() after pthread_create()" problem. Applications could accomplish the same, but since it's such a common operation, provide a little help. --- lib/librumpuser/Makefile | 4 +- lib/librumpuser/rumpuser_daemonize.c | 123 +++++++++++++++++++++++++++ sys/rump/include/rump/rump.h | 10 ++- sys/rump/include/rump/rumpuser.h | 5 +- sys/rump/librump/rumpkern/rump.c | 35 ++++++-- 5 files changed, 162 insertions(+), 15 deletions(-) create mode 100644 lib/librumpuser/rumpuser_daemonize.c diff --git a/lib/librumpuser/Makefile b/lib/librumpuser/Makefile index 4e894f8b58a6..1c0061b0b174 100644 --- a/lib/librumpuser/Makefile +++ b/lib/librumpuser/Makefile @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.4 2010/11/30 14:08:39 pooka Exp $ +# $NetBSD: Makefile,v 1.5 2010/11/30 14:23:24 pooka Exp $ # WARNS= 4 @@ -12,7 +12,7 @@ LIBDPLIBS+= pthread ${.CURDIR}/../libpthread SRCS= rumpuser.c rumpuser_net.c SRCS+= rumpuser_pth.c -SRCS+= rumpuser_dl.c rumpuser_sp.c +SRCS+= rumpuser_dl.c rumpuser_sp.c rumpuser_daemonize.c INCSDIR= /usr/include/rump INCS= rumpuser.h diff --git a/lib/librumpuser/rumpuser_daemonize.c b/lib/librumpuser/rumpuser_daemonize.c new file mode 100644 index 000000000000..a1d62a87efc8 --- /dev/null +++ b/lib/librumpuser/rumpuser_daemonize.c @@ -0,0 +1,123 @@ +/* $NetBSD: rumpuser_daemonize.c,v 1.1 2010/11/30 14:23:24 pooka Exp $ */ + +/* + * Copyright (c) 2010 Antti Kantee. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#if !defined(lint) +__RCSID("$NetBSD: rumpuser_daemonize.c,v 1.1 2010/11/30 14:23:24 pooka Exp $"); +#endif /* !lint */ + +#include +#include + +#include +#include +#include +#include +#include + +static int isdaemonizing; +static int daemonpipe[2]; + +#include + +int +rumpuser_daemonize_begin(void) +{ + ssize_t n; + int error; + + if (isdaemonizing) + return EINPROGRESS; + isdaemonizing = 1; + + /* + * For daemons we need to fork. However, since we can't fork + * after rump_init (which creates threads), do it now. Add + * a little pipe trickery to make sure we don't exit until the + * service is fully inited (i.e. interlocked daemonization). + * Actually, use sucketpair since that allows to easily steer + * clear of the dreaded sigpipe. + * + * Note: We do *NOT* host chdir("/"). It's up to the caller to + * take care of that or not. + */ + if (socketpair(PF_LOCAL, SOCK_STREAM, 0, daemonpipe) == -1) { + return errno; + } + + switch (fork()) { + case 0: + if (setsid() == -1) { + rumpuser_daemonize_done(errno); + } + return 0; + case -1: + return errno; + default: + close(daemonpipe[1]); + n = recv(daemonpipe[0], &error, sizeof(error), MSG_NOSIGNAL); + if (n == -1) + error = errno; + else if (n != sizeof(error)) + error = ESRCH; + _exit(error); + } +} + +int +rumpuser_daemonize_done(int error) +{ + ssize_t n; + int fd; + + if (!isdaemonizing) + return ENOENT; + + if (error == 0) { + fd = open(_PATH_DEVNULL, O_RDWR); + if (fd == -1) { + error = errno; + goto out; + } + dup2(fd, STDIN_FILENO); + dup2(fd, STDOUT_FILENO); + dup2(fd, STDERR_FILENO); + if (fd > STDERR_FILENO) + close(fd); + } + + out: + n = send(daemonpipe[1], &error, sizeof(error), MSG_NOSIGNAL); + if (n != sizeof(error)) + return EPIPE; + else if (n == -1) + return errno; + close(daemonpipe[0]); + close(daemonpipe[1]); + + return 0; +} diff --git a/sys/rump/include/rump/rump.h b/sys/rump/include/rump/rump.h index 4720ae8a82cd..67da15a84b7b 100644 --- a/sys/rump/include/rump/rump.h +++ b/sys/rump/include/rump/rump.h @@ -1,4 +1,4 @@ -/* $NetBSD: rump.h,v 1.48 2010/11/30 10:46:59 dholland Exp $ */ +/* $NetBSD: rump.h,v 1.49 2010/11/30 14:23:24 pooka Exp $ */ /* * Copyright (c) 2007 Antti Kantee. All Rights Reserved. @@ -88,8 +88,8 @@ enum rump_etfs_type { * Something like rump capabilities would be nicer, but let's * do this for a start. */ -#define RUMP_VERSION 01 -#define rump_init() rump__init(RUMP_VERSION) +#define RUMP_VERSION 01 +#define rump_init() rump__init(RUMP_VERSION) /* um, what's the point ?-) */ #ifdef _BEGIN_DECLS @@ -105,7 +105,11 @@ void rump_unschedule(void); void rump_printevcnts(void); +int rump_daemonize_begin(void); int rump__init(int); +int rump_init_server(const char *); +int rump_daemonize_done(int); +#define RUMP_DAEMONIZE_SUCCESS 0 #ifndef _KERNEL #include diff --git a/sys/rump/include/rump/rumpuser.h b/sys/rump/include/rump/rumpuser.h index 5e809f547337..7006548cf62b 100644 --- a/sys/rump/include/rump/rumpuser.h +++ b/sys/rump/include/rump/rumpuser.h @@ -1,4 +1,4 @@ -/* $NetBSD: rumpuser.h,v 1.53 2010/11/25 17:59:02 pooka Exp $ */ +/* $NetBSD: rumpuser.h,v 1.54 2010/11/30 14:23:24 pooka Exp $ */ /* * Copyright (c) 2007 Antti Kantee. All Rights Reserved. @@ -39,6 +39,9 @@ #define RUMPUSER_VERSION 6 int rumpuser_getversion(void); +int rumpuser_daemonize_begin(void); +int rumpuser_daemonize_done(int); + struct msghdr; struct pollfd; struct sockaddr; diff --git a/sys/rump/librump/rumpkern/rump.c b/sys/rump/librump/rumpkern/rump.c index 83a0e7157a34..5e17405a8bec 100644 --- a/sys/rump/librump/rumpkern/rump.c +++ b/sys/rump/librump/rumpkern/rump.c @@ -1,4 +1,4 @@ -/* $NetBSD: rump.c,v 1.206 2010/11/22 20:42:19 pooka Exp $ */ +/* $NetBSD: rump.c,v 1.207 2010/11/30 14:23:24 pooka Exp $ */ /* * Copyright (c) 2007 Antti Kantee. All Rights Reserved. @@ -28,7 +28,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: rump.c,v 1.206 2010/11/22 20:42:19 pooka Exp $"); +__KERNEL_RCSID(0, "$NetBSD: rump.c,v 1.207 2010/11/30 14:23:24 pooka Exp $"); #include #define ELFSIZE ARCH_ELFSIZE @@ -204,6 +204,23 @@ static const struct rumpuser_sp_ops spops = { .spop_getpid = spgetpid, }; +int +rump_daemonize_begin(void) +{ + + if (rump_inited) + return EALREADY; + + return rumpuser_daemonize_begin(); +} + +int +rump_daemonize_done(int error) +{ + + return rumpuser_daemonize_done(error); +} + int rump__init(int rump_version) { @@ -222,13 +239,6 @@ rump__init(int rump_version) else rump_inited = 1; - /* Check our role as a rump proxy */ - if (rumpuser_getenv("RUMP_SP_SERVER", buf, sizeof(buf), &error) == 0) { - error = rumpuser_sp_init(&spops, buf); - if (error) - return error; - } - if (rumpuser_getversion() != RUMPUSER_VERSION) { /* let's hope the ABI of rumpuser_dprintf is the same ;) */ rumpuser_dprintf("rumpuser version mismatch: %d vs. %d\n", @@ -434,6 +444,13 @@ rump__init(int rump_version) return 0; } +int +rump_init_server(const char *url) +{ + + return rumpuser_sp_init(&spops, url); +} + void cpu_reboot(int howto, char *bootstr) {