Commit 3d67411d by Marek Majkowski

Merge remote-tracking branch 'lxc/master' into share-namespaces

parents 3c93577b bdb3f441
......@@ -135,6 +135,9 @@ int lxc_abstract_unix_connect(const char *path)
if (connect(fd, (struct sockaddr *)&addr, offsetof(struct sockaddr_un, sun_path) + len)) {
int tmp = errno;
/* special case to connect to older containers */
if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) == 0)
return fd;
process_lock();
close(fd);
process_unlock();
......
......@@ -49,25 +49,6 @@
#include "config.h"
#include "utils.h"
#ifndef HAVE_GETLINE
#ifdef HAVE_FGETLN
#include <../include/getline.h>
#endif
#endif
/* Define setns() if missing from the C library */
#ifndef HAVE_SETNS
static inline int setns(int fd, int nstype)
{
#ifdef __NR_setns
return syscall(__NR_setns, fd, nstype);
#else
errno = ENOSYS;
return -1;
#endif
}
#endif
#if ISTEST
#define CONF_FILE "/tmp/lxc-usernet"
#define DB_FILE "/tmp/nics"
......@@ -76,7 +57,6 @@ static inline int setns(int fd, int nstype)
#define DB_FILE LXC_USERNIC_DB
#endif
#include "nl.h"
#ifndef IFLA_LINKMODE
......
......@@ -491,7 +491,7 @@ static bool lxcapi_wait(struct lxc_container *c, const char *state, int timeout)
}
static bool wait_on_daemonized_start(struct lxc_container *c)
static bool wait_on_daemonized_start(struct lxc_container *c, int pid)
{
/* we'll probably want to make this timeout configurable? */
int timeout = 5, ret, status;
......@@ -500,12 +500,44 @@ static bool wait_on_daemonized_start(struct lxc_container *c)
* our child is going to fork again, then exit. reap the
* child
*/
ret = wait(&status);
ret = waitpid(pid, &status, 0);
if (ret == -1 || !WIFEXITED(status) || WEXITSTATUS(status) != 0)
DEBUG("failed waiting for first dual-fork child");
return lxcapi_wait(c, "RUNNING", timeout);
}
static bool am_single_threaded(void)
{
struct dirent dirent, *direntp;
DIR *dir;
int count=0;
process_lock();
dir = opendir("/proc/self/task");
process_unlock();
if (!dir) {
INFO("failed to open /proc/self/task");
return false;
}
while (!readdir_r(dir, &dirent, &direntp)) {
if (!direntp)
break;
if (!strcmp(direntp->d_name, "."))
continue;
if (!strcmp(direntp->d_name, ".."))
continue;
if (++count > 1)
break;
}
process_lock();
closedir(dir);
process_unlock();
return count == 1;
}
/*
* I can't decide if it'd be more convenient for callers if we accept '...',
* or a null-terminated array (i.e. execl vs execv)
......@@ -575,7 +607,7 @@ static bool lxcapi_start(struct lxc_container *c, int useinit, char * const argv
return false;
}
if (pid != 0)
return wait_on_daemonized_start(c);
return wait_on_daemonized_start(c, pid);
process_unlock(); // we're no longer sharing
/* second fork to be reparented by init */
......@@ -598,6 +630,11 @@ static bool lxcapi_start(struct lxc_container *c, int useinit, char * const argv
open("/dev/null", O_RDWR);
open("/dev/null", O_RDWR);
setsid();
} else {
if (!am_single_threaded()) {
ERROR("Cannot start non-daemonized container when threaded");
return false;
}
}
reboot:
......
......@@ -36,6 +36,7 @@ static struct option options[] = {
{ "iterations", required_argument, NULL, 'i' },
{ "template", required_argument, NULL, 't' },
{ "delay", required_argument, NULL, 'd' },
{ "modes", required_argument, NULL, 'm' },
{ "quiet", no_argument, NULL, 'q' },
{ "help", no_argument, NULL, '?' },
{ 0, 0, 0, 0 },
......@@ -44,13 +45,14 @@ static struct option options[] = {
static void usage(void) {
fprintf(stderr, "Usage: lxc-test-concurrent [OPTION]...\n\n"
"Common options :\n"
" -j, --threads=N Threads to run concurrently\n"
" (default: 5, use 1 for no threading)\n"
" -i, --iterations=N Number times to run the test (default: 1)\n"
" -t, --template=t Template to use (default: busybox)\n"
" -d, --delay=N Delay in seconds between start and stop\n"
" -q, --quiet Don't produce any output\n"
" -?, --help Give this help list\n"
" -j, --threads=N Threads to run concurrently\n"
" (default: 5, use 1 for no threading)\n"
" -i, --iterations=N Number times to run the test (default: 1)\n"
" -t, --template=t Template to use (default: busybox)\n"
" -d, --delay=N Delay in seconds between start and stop\n"
" -m, --modes=<mode,mode,...> Modes to run (create, start, stop, destroy)\n"
" -q, --quiet Don't produce any output\n"
" -?, --help Give this help list\n"
"\n"
"Mandatory or optional arguments to long options are also mandatory or optional\n"
"for any corresponding short options.\n\n");
......@@ -135,11 +137,12 @@ int main(int argc, char *argv[]) {
pthread_t *threads;
struct thread_args *args;
char *modes[] = {"create", "start", "stop", "destroy", NULL};
char *modes_default[] = {"create", "start", "stop", "destroy", NULL};
char **modes = modes_default;
pthread_attr_init(&attr);
while ((opt = getopt_long(argc, argv, "j:i:t:d:q", options, NULL)) != -1) {
while ((opt = getopt_long(argc, argv, "j:i:t:d:m:q", options, NULL)) != -1) {
switch(opt) {
case 'j':
nthreads = atoi(optarg);
......@@ -156,6 +159,19 @@ int main(int argc, char *argv[]) {
case 'q':
quiet = 1;
break;
case 'm': {
char *mode_tok, *tok, *saveptr;
modes = NULL;
for (i = 0, mode_tok = optarg;
(tok = strtok_r(mode_tok, ",", &saveptr));
i++, mode_tok = NULL) {
modes = realloc(modes, sizeof(*modes) * (i+2));
modes[i] = tok;
}
modes[i] = NULL;
break;
}
default: /* '?' */
usage();
exit(EXIT_FAILURE);
......
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