[lxc-devel] [PATCH 1/2] Modify lxc_attach and lxc_init to use clone instead of fork.
Vladimir Smirnov
civil at yandex-team.ru
Wed Aug 24 10:17:49 UTC 2011
Clone allows more flexible control. Currently, if there is any inherited fd,
lxc-start exits with error. With clone it's possible not to pass open fd's to childs.
Signed-off-by: Vladimir Smirnov <civil at yandex-team.ru>
---
src/lxc/lxc_attach.c | 79 +++++++++++++++++++++++++++++---------------------
src/lxc/lxc_init.c | 46 ++++++++++++++++++-----------
2 files changed, 75 insertions(+), 50 deletions(-)
diff --git a/src/lxc/lxc_attach.c b/src/lxc/lxc_attach.c
index ed3d5a4..930865e 100644
--- a/src/lxc/lxc_attach.c
+++ b/src/lxc/lxc_attach.c
@@ -20,6 +20,7 @@
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#define STACKSIZE 16384
#define _GNU_SOURCE
#include <unistd.h>
@@ -29,6 +30,7 @@
#include <sys/param.h>
#include <sys/types.h>
#include <sys/wait.h>
+#include <sched.h>
#include "commands.h"
#include "arguments.h"
@@ -56,14 +58,48 @@ Options :\n\
.checker = NULL,
};
+static char *envp_global;
+
+int child_main()
+{
+ struct passwd *passwd;
+ uid_t uid;
+
+ if (my_args.argc) {
+ execve(my_args.argv[0], my_args.argv, envp_global);
+ SYSERROR("failed to exec '%s'", my_args.argv[0]);
+ return -1;
+ }
+
+ uid = getuid();
+
+ passwd = getpwuid(uid);
+ if (!passwd) {
+ SYSERROR("failed to get passwd " \
+ "entry for uid '%d'", uid);
+ return -1;
+ }
+
+ {
+ char *const args[] = {
+ passwd->pw_shell,
+ NULL,
+ };
+
+ execve(args[0], args, envp_global);
+ SYSERROR("failed to exec '%s'", args[0]);
+ return -1;
+ }
+}
+
int main(int argc, char *argv[], char *envp[])
{
int ret;
pid_t pid;
- struct passwd *passwd;
- uid_t uid;
char *curdir;
+ envp_global = envp;
+
ret = lxc_caps_init();
if (ret)
return ret;
@@ -96,7 +132,14 @@ int main(int argc, char *argv[], char *envp[])
free(curdir);
- pid = fork();
+ void **newstack;
+ newstack = (void **) malloc(STACKSIZE);
+ if (!newstack)
+ exit(newstack);
+
+ newstack = (void **)(STACKSIZE + (char *)newstack);
+ *--newstack = 0;
+ pid = clone(child_main, newstack, CLONE_VM | CLONE_FS | CLONE_SIGHAND, 0);
if (pid < 0) {
SYSERROR("failed to fork");
@@ -120,35 +163,5 @@ int main(int argc, char *argv[], char *envp[])
return -1;
}
- if (!pid) {
-
- if (my_args.argc) {
- execve(my_args.argv[0], my_args.argv, envp);
- SYSERROR("failed to exec '%s'", my_args.argv[0]);
- return -1;
- }
-
- uid = getuid();
-
- passwd = getpwuid(uid);
- if (!passwd) {
- SYSERROR("failed to get passwd " \
- "entry for uid '%d'", uid);
- return -1;
- }
-
- {
- char *const args[] = {
- passwd->pw_shell,
- NULL,
- };
-
- execve(args[0], args, envp);
- SYSERROR("failed to exec '%s'", args[0]);
- return -1;
- }
-
- }
-
return 0;
}
diff --git a/src/lxc/lxc_init.c b/src/lxc/lxc_init.c
index a534b51..7debd6f 100644
--- a/src/lxc/lxc_init.c
+++ b/src/lxc/lxc_init.c
@@ -20,6 +20,7 @@
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#define STACKSIZE 16384
#include <stdio.h>
#include <unistd.h>
@@ -32,6 +33,7 @@
#include <sys/wait.h>
#define _GNU_SOURCE
#include <getopt.h>
+#include <sched.h>
#include "log.h"
#include "caps.h"
@@ -40,6 +42,9 @@
lxc_log_define(lxc_init, lxc);
+static sigset_t mask, omask;
+static char **aargv;
+
static int quiet;
static struct option options[] = {
@@ -49,6 +54,23 @@ static struct option options[] = {
static int was_interrupted = 0;
+int child_main()
+{
+ int i;
+ int err = -1;
+ /* restore default signal handlers */
+ for (i = 1; i < NSIG; i++)
+ signal(i, SIG_DFL);
+
+ sigprocmask(SIG_SETMASK, &omask, NULL);
+
+ NOTICE("about to exec '%s'", aargv[0]);
+
+ execvp(aargv[0], aargv);
+ ERROR("failed to exec: '%s' : %m", aargv[0]);
+ exit(err);
+}
+
int main(int argc, char *argv[])
{
@@ -61,8 +83,6 @@ int main(int argc, char *argv[])
pid_t pid;
int nbargs = 0;
int err = -1;
- char **aargv;
- sigset_t mask, omask;
int i, shutdown = 0;
while (1) {
@@ -115,25 +135,17 @@ int main(int argc, char *argv[])
if (lxc_caps_reset())
exit(err);
- pid = fork();
-
- if (pid < 0)
+ void **newstack;
+ newstack = (void **) malloc(STACKSIZE);
+ if (!newstack)
exit(err);
- if (!pid) {
-
- /* restore default signal handlers */
- for (i = 1; i < NSIG; i++)
- signal(i, SIG_DFL);
+ newstack = (void **)(STACKSIZE + (char *)newstack);
+ *--newstack = 0;
+ pid = clone(child_main, newstack, CLONE_VM | CLONE_FS | CLONE_SIGHAND, 0);
- sigprocmask(SIG_SETMASK, &omask, NULL);
-
- NOTICE("about to exec '%s'", aargv[0]);
-
- execvp(aargv[0], aargv);
- ERROR("failed to exec: '%s' : %m", aargv[0]);
+ if (pid < 0)
exit(err);
- }
/* let's process the signals now */
sigdelset(&omask, SIGALRM);
--
1.7.6
More information about the lxc-devel
mailing list