diff --git a/configure.ac b/configure.ac
index f82e7df75..4c8c50f4b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -95,6 +95,7 @@ AC_CONFIG_FILES([
doc/lxc-ls.sgml
doc/lxc-ps.sgml
doc/lxc-cgroup.sgml
+ doc/lxc-kill.sgml
doc/lxc.conf.sgml
doc/lxc.sgml
doc/common_options.sgml
diff --git a/doc/Makefile.am b/doc/Makefile.am
index bd96c9933..54e5f2217 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -20,6 +20,7 @@ man_MANS = \
lxc-ls.1 \
lxc-ps.1 \
lxc-cgroup.1 \
+ lxc-kill.1 \
\
lxc.conf.5 \
\
diff --git a/doc/lxc-execute.sgml.in b/doc/lxc-execute.sgml.in
index fe51b9bf3..7bd009807 100644
--- a/doc/lxc-execute.sgml.in
+++ b/doc/lxc-execute.sgml.in
@@ -86,6 +86,12 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
container, lxc-init has the pid 1 and the
first process of the application has the pid 2.
+
+ The above lxc-init is designed to forward received
+ signals to the started command.
+ So lxc-kill (1) sent signal is received
+ by the user specified command (pid 2 in the container).
+
diff --git a/doc/lxc-kill.sgml.in b/doc/lxc-kill.sgml.in
new file mode 100644
index 000000000..c3373c6fa
--- /dev/null
+++ b/doc/lxc-kill.sgml.in
@@ -0,0 +1,91 @@
+
+
+
+
+
+mcr
+">
+
+]>
+
+
+
+ @LXC_GENERATE_DATE@
+
+
+ lxc-kill
+ 1
+ IBM
+
+
+
+ lxc-kill
+
+
+ Send a signal to the process 1 of the container.
+
+
+
+
+
+ lxc-kill --name=NAME SIGNUM
+
+
+
+
+ Description
+
+
+ lxc-kill send
+ the SIGNUM signal to the first process of the container.
+
+
+
+ If this command is used on an application container ran by
+ lxc-execute, the lxc-init will receive the signal and will forward it to
+ the process 2 which is the command specified in the command line. See
+ lxc-execute (1).
+
+
+
+ &commonoptions;
+
+
+ Examples
+
+
+ To send the signal 26 to the process pi1 running in container
+ 123 :
+
+
+
+ lxc-execute -n 123 -- pi1 -d 500000
+ lxc-kill --name=123 26
+
+
+
+
+ ©rights;
+
+ &seealso;
+
+
+
+
diff --git a/doc/see_also.sgml.in b/doc/see_also.sgml.in
index 93b9344b9..78b99b46b 100644
--- a/doc/see_also.sgml.in
+++ b/doc/see_also.sgml.in
@@ -57,6 +57,11 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1
,
+
+ lxc-kill
+ 1
+ ,
+
lxc-console
1
diff --git a/src/lxc/Makefile.am b/src/lxc/Makefile.am
index 4c4783df1..510bc9dca 100644
--- a/src/lxc/Makefile.am
+++ b/src/lxc/Makefile.am
@@ -82,7 +82,8 @@ bin_PROGRAMS = \
lxc-cgroup \
lxc-unfreeze \
lxc-checkpoint \
- lxc-restart
+ lxc-restart \
+ lxc-kill
libexec_PROGRAMS = \
lxc-init
@@ -105,6 +106,7 @@ lxc_stop_SOURCES = lxc_stop.c
lxc_unfreeze_SOURCES = lxc_unfreeze.c
lxc_unshare_SOURCES = lxc_unshare.c
lxc_wait_SOURCES = lxc_wait.c
+lxc_kill_SOURCES = lxc_kill.c
install-exec-local: install-soPROGRAMS
mv $(DESTDIR)$(libdir)/liblxc.so $(DESTDIR)$(libdir)/liblxc.so.$(VERSION)
diff --git a/src/lxc/lxc_init.c b/src/lxc/lxc_init.c
index b0b7ac7c9..a34818e5f 100644
--- a/src/lxc/lxc_init.c
+++ b/src/lxc/lxc_init.c
@@ -46,12 +46,23 @@ static struct option options[] = {
{ 0, 0, 0, 0 },
};
+static int was_interrupted = 0;
+
int main(int argc, char *argv[])
{
+
+ void interrupt_handler(int sig)
+ {
+ if (!was_interrupted)
+ was_interrupted = sig;
+ }
+
pid_t pid;
int nbargs = 0;
int err = -1;
char **aargv;
+ sigset_t mask, omask;
+ int i;
while (1) {
int ret = getopt_long_only(argc, argv, "", options, NULL);
@@ -75,6 +86,18 @@ int main(int argc, char *argv[])
aargv = &argv[optind];
argc -= nbargs;
+ sigfillset(&mask);
+ sigprocmask(SIG_SETMASK, &mask, &omask);
+
+ for (i = 1; i < NSIG; i++) {
+ struct sigaction act;
+
+ sigfillset(&act.sa_mask);
+ act.sa_flags = 0;
+ act.sa_handler = interrupt_handler;
+ sigaction(i, &act, NULL);
+ }
+
pid = fork();
if (pid < 0)
@@ -82,6 +105,10 @@ int main(int argc, char *argv[])
if (!pid) {
+ for (i = 1; i < NSIG; i++)
+ signal(i, SIG_DFL);
+ sigprocmask(SIG_SETMASK, &omask, NULL);
+
if (lxc_setup_fs())
exit(err);
@@ -92,6 +119,8 @@ int main(int argc, char *argv[])
exit(err);
}
+ sigprocmask(SIG_SETMASK, &omask, NULL);
+
/* no need of other inherited fds but stderr */
close(fileno(stdin));
close(fileno(stdout));
@@ -102,6 +131,11 @@ int main(int argc, char *argv[])
int orphan = 0;
pid_t waited_pid;
+ if (was_interrupted) {
+ kill(pid, was_interrupted);
+ was_interrupted = 0;
+ }
+
waited_pid = wait(&status);
if (waited_pid < 0) {
if (errno == ECHILD)
diff --git a/src/lxc/lxc_kill.c b/src/lxc/lxc_kill.c
new file mode 100644
index 000000000..3d996a5c7
--- /dev/null
+++ b/src/lxc/lxc_kill.c
@@ -0,0 +1,92 @@
+/*
+ * lxc: linux Container library
+ *
+ * (C) Copyright IBM Corp. 2007, 2010
+ *
+ * Authors:
+ * Daniel Lezcano
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include "commands.h"
+#include "arguments.h"
+#include "namespace.h"
+#include "log.h"
+
+lxc_log_define(lxc_kill_ui, lxc);
+
+static const struct option my_longopts[] = {
+ LXC_COMMON_OPTIONS
+};
+
+static struct lxc_arguments my_args = {
+ .progname = "lxc-kill",
+ .help = "\
+--name=NAME SIGNUM\n\
+\n\
+Sends signal number SIGNUM to the first user process in container NAME\n\
+\n\
+Options :\n\
+ -n, --name=NAME NAME for name of the container\n",
+ .options = my_longopts,
+ .parser = NULL,
+ .checker = NULL,
+};
+
+int main(int argc, char *argv[], char *envp[])
+{
+ int ret;
+ pid_t pid;
+ int sig;
+
+ ret = lxc_arguments_parse(&my_args, argc, argv);
+ if (ret)
+ return ret;
+
+ ret = lxc_log_init(my_args.log_file, my_args.log_priority,
+ my_args.progname, my_args.quiet);
+ if (ret)
+ return ret;
+
+ if (my_args.argc) {
+ sig = atoi(my_args.argv[0]);
+ if (!sig || sig >= NSIG) {
+ ERROR("'%s' isn't a valid signal number",
+ my_args.argv[0]);
+ return -1;
+ }
+ } else
+ sig=SIGKILL;
+
+ pid = get_init_pid(my_args.name);
+ if (pid < 0) {
+ ERROR("failed to get the init pid");
+ return -1;
+ }
+
+ ret = kill(pid, sig);
+ if (ret < 0) {
+ ERROR("failed to kill the init pid");
+ return -1;
+ }
+
+ return 0;
+}