AM_CFLAGS = $(COMMON_FLAGS)
AM_CFLAGS += -Wstrict-prototypes -I $(top_srcdir)/include
+rundir = $(localstatedir)/run
+AM_CFLAGS += -DRUNDIR=\"$(rundir)\"
+
if !NDEBUG
AM_LDFLAGS = -export-dynamic
endif
#include "buffer.h"
#include "command-line.h"
#include "compiler.h"
+#include "daemon.h"
#include "fault.h"
#include "learning-switch.h"
#include "poll-loop.h"
fatal(0, "no active or passive switch connections");
}
+ daemonize();
+
while (n_switches > 0 || n_listeners > 0) {
int iteration;
int i;
parse_options(int argc, char *argv[])
{
static struct option long_options[] = {
+ {"detach", no_argument, 0, 'D'},
+ {"pidfile", optional_argument, 0, 'P'},
{"hub", no_argument, 0, 'H'},
{"noflow", no_argument, 0, 'n'},
{"verbose", optional_argument, 0, 'v'},
}
switch (c) {
+ case 'D':
+ set_detach();
+ break;
+
+ case 'P':
+ set_pidfile(optarg ? optarg : "controller.pid");
+ break;
+
case 'H':
learn_macs = false;
break;
program_name, program_name);
vconn_usage(true, true);
printf("\nOther options:\n"
+ " -D, --detach run in background as daemon\n"
+ " -P, --pidfile[=FILE] create pidfile (default: %s/controller.pid)\n"
" -H, --hub act as hub instead of learning switch\n"
" -n, --noflow pass traffic, but don't add flows\n"
" -v, --verbose set maximum verbosity level\n"
" -h, --help display this help message\n"
- " -V, --version display version information\n");
+ " -V, --version display version information\n",
+ RUNDIR);
exit(EXIT_SUCCESS);
}
buffer.h \
command-line.h \
compiler.h \
+ daemon.h \
dynamic-string.h \
dpif.h \
fatal-signal.h \
--- /dev/null
+/* Copyright (c) 2008 The Board of Trustees of The Leland Stanford
+ * Junior University
+ *
+ * We are making the OpenFlow specification and associated documentation
+ * (Software) available for public use and benefit with the expectation
+ * that others will use, modify and enhance the Software and contribute
+ * those enhancements back to the community. However, since we would
+ * like to make the Software available for broadest use, with as few
+ * restrictions as possible permission is hereby granted, free of
+ * charge, to any person obtaining a copy of this Software to deal in
+ * the Software under the copyrights without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * The name and trademarks of copyright holder(s) may NOT be used in
+ * advertising or publicity pertaining to the Software or any
+ * derivatives without specific, written prior permission.
+ */
+
+#ifndef DAEMON_H
+#define DAEMON_H 1
+
+void set_pidfile(const char *name);
+void set_detach(void);
+void daemonize(void);
+
+#endif /* daemon.h */
void fatal_signal_add_hook(void (*)(void *aux), void *aux);
void fatal_signal_block(void);
void fatal_signal_unblock(void);
+void fatal_signal_fork(void);
/* Convenience functions for unlinking files upon termination.
*
VLOG_MODULE(chain) \
VLOG_MODULE(controller) \
VLOG_MODULE(ctlpath) \
+ VLOG_MODULE(daemon) \
VLOG_MODULE(datapath) \
VLOG_MODULE(dpif) \
VLOG_MODULE(dpctl) \
libopenflow_la_SOURCES = \
buffer.c \
command-line.c \
+ daemon.c \
dynamic-string.c \
fatal-signal.c \
fault.c \
--- /dev/null
+/* Copyright (c) 2008 The Board of Trustees of The Leland Stanford
+ * Junior University
+ *
+ * We are making the OpenFlow specification and associated documentation
+ * (Software) available for public use and benefit with the expectation
+ * that others will use, modify and enhance the Software and contribute
+ * those enhancements back to the community. However, since we would
+ * like to make the Software available for broadest use, with as few
+ * restrictions as possible permission is hereby granted, free of
+ * charge, to any person obtaining a copy of this Software to deal in
+ * the Software under the copyrights without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * The name and trademarks of copyright holder(s) may NOT be used in
+ * advertising or publicity pertaining to the Software or any
+ * derivatives without specific, written prior permission.
+ */
+
+#include "daemon.h"
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "fatal-signal.h"
+#include "util.h"
+
+#define THIS_MODULE VLM_daemon
+#include "vlog.h"
+
+/* Should we run in the background? */
+static bool detach;
+
+/* Name of pidfile (null if none). */
+static char *pidfile;
+
+/* Sets up a following call to daemonize() to create a pidfile named 'name'.
+ * If 'name' begins with '/', then it is treated as an absolute path.
+ * Otherwise, it is taken relative to RUNDIR, which is $(prefix)/var/run by
+ * default. */
+void
+set_pidfile(const char *name)
+{
+ free(pidfile);
+ pidfile = *name == '/' ? xstrdup(name) : xasprintf("%s/%s", RUNDIR, name);
+}
+
+/* Sets up a following call to daemonize() to detach from the foreground
+ * session, running this process in the background. */
+void
+set_detach(void)
+{
+ detach = true;
+}
+
+/* If a pidfile has been configured, creates it and stores 'pid' in it. It is
+ * the caller's responsibility to make sure that the pidfile will eventually
+ * be deleted. */
+static void
+make_pidfile(pid_t pid)
+{
+ if (pidfile) {
+ FILE *file;
+
+ file = fopen(pidfile, "w");
+ if (file) {
+ fprintf(file, "%ld\n", (long int) pid);
+ fclose(file);
+ } else {
+ VLOG_ERR("failed to create \"%s\": %s", pidfile, strerror(errno));
+ }
+ free(pidfile);
+ pidfile = NULL;
+ }
+}
+
+/* If configured with set_pidfile() or set_detach(), creates the pid file and
+ * detaches from the foreground session. */
+void
+daemonize(void)
+{
+ if (detach) {
+ pid_t pid;
+
+ /* Fork and exit from the parent. */
+ pid = fork();
+ if (pid < 0) {
+ fatal(errno, "could not fork");
+ } else if (pid) {
+ fatal_signal_fork();
+ make_pidfile(pid);
+ exit(0);
+ }
+
+ if (pidfile) {
+ fatal_signal_add_file_to_unlink(pidfile);
+ }
+ setsid();
+ chdir("/");
+ } else {
+ if (pidfile) {
+ fatal_signal_add_file_to_unlink(pidfile);
+ }
+ make_pidfile(getpid());
+ }
+}
+
\f
static char **files;
static size_t n_files, max_files;
+static bool disabled;
static void unlink_files(void *aux);
static void do_unlink_files(void);
static void
unlink_files(void *aux UNUSED)
{
- do_unlink_files();
+ do_unlink_files();
}
static void
do_unlink_files(void)
+{
+ if (!disabled) {
+ size_t i;
+
+ for (i = 0; i < n_files; i++) {
+ unlink(files[i]);
+ }
+ }
+}
+\f
+/* Disables the fatal signal hook mechanism. Following a fork, one of the
+ * resulting processes can call this function to allow it to terminate without
+ * triggering fatal signal processing or removing files. Fatal signal
+ * processing is still enabled in the other process. */
+void
+fatal_signal_fork(void)
{
size_t i;
- for (i = 0; i < n_files; i++) {
- unlink(files[i]);
+ disabled = true;
+
+ for (i = 0; i < ARRAY_SIZE(fatal_signals); i++) {
+ int sig_nr = fatal_signals[i];
+ if (signal(sig_nr, SIG_DFL) == SIG_IGN) {
+ signal(sig_nr, SIG_IGN);
+ }
}
}
\f
#include "buffer.h"
#include "command-line.h"
#include "compiler.h"
+#include "daemon.h"
#include "fault.h"
#include "flow.h"
#include "learning-switch.h"
fatal(retval, "Could not listen for vlog connections");
}
+ daemonize();
+
relay_create(rconn_new(argv[optind], 1), rconn_new(argv[optind + 1], 1),
false);
for (;;) {
{"fail", required_argument, 0, 'f'},
{"fail-open-delay", required_argument, 0, 'd'},
{"listen", required_argument, 0, 'l'},
+ {"detach", no_argument, 0, 'D'},
+ {"pidfile", optional_argument, 0, 'P'},
{"verbose", optional_argument, 0, 'v'},
{"help", no_argument, 0, 'h'},
{"version", no_argument, 0, 'V'},
}
break;
+ case 'D':
+ set_detach();
+ break;
+
+ case 'P':
+ set_pidfile(optarg ? optarg : "secchan.pid");
+ break;
+
case 'l':
if (listen_vconn_name) {
fatal(0, "-l or --listen may be only specified once");
" -l, --listen=METHOD allow management connections on METHOD\n"
" (a passive OpenFlow connection method)\n"
"\nOther options:\n"
+ " -D, --detach run in background as daemon\n"
+ " -P, --pidfile[=FILE] create pidfile (default: %s/secchan.pid)\n"
" -v, --verbose set maximum verbosity level\n"
" -h, --help display this help message\n"
- " -V, --version display version information\n");
+ " -V, --version display version information\n",
+ RUNDIR);
exit(EXIT_SUCCESS);
}
#include <string.h>
#include "command-line.h"
+#include "daemon.h"
#include "datapath.h"
#include "fault.h"
#include "openflow.h"
fatal(error, "could not listen for vlog connections");
}
+ daemonize();
+
for (;;) {
dp_run(dp);
dp_wait(dp);
{"interfaces", required_argument, 0, 'i'},
{"datapath-id", required_argument, 0, 'd'},
{"listen", required_argument, 0, 'l'},
+ {"detach", no_argument, 0, 'D'},
+ {"pidfile", optional_argument, 0, 'P'},
{"verbose", optional_argument, 0, 'v'},
{"help", no_argument, 0, 'h'},
{"version", no_argument, 0, 'V'},
printf("%s "VERSION" compiled "__DATE__" "__TIME__"\n", argv[0]);
exit(EXIT_SUCCESS);
+ case 'D':
+ set_detach();
+ break;
+
+ case 'P':
+ set_pidfile(optarg ? optarg : "switch.pid");
+ break;
+
case 'v':
vlog_set_verbosity(optarg);
break;
" -l, --listen=METHOD allow management connections on METHOD\n"
" (a passive OpenFlow connection method)\n"
"\nOther options:\n"
+ " -D, --detach run in background as daemon\n"
+ " -P, --pidfile[=FILE] create pidfile (default: %s/switch.pid)\n"
" -v, --verbose set maximum verbosity level\n"
" -h, --help display this help message\n"
- " -V, --version display version information\n");
+ " -V, --version display version information\n",
+ RUNDIR);
exit(EXIT_SUCCESS);
}