Skip to content

Commit

Permalink
Merge remote-tracking branch 'lxc/master' into share-namespaces
Browse files Browse the repository at this point in the history
  • Loading branch information
majek committed Nov 12, 2013
2 parents 3c93577 + bdb3f44 commit 3d67411
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 32 deletions.
3 changes: 3 additions & 0 deletions src/lxc/af_unix.c
Expand Up @@ -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();
Expand Down
20 changes: 0 additions & 20 deletions src/lxc/lxc_user_nic.c
Expand Up @@ -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"
Expand All @@ -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
Expand Down
43 changes: 40 additions & 3 deletions src/lxc/lxccontainer.c
Expand Up @@ -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;
Expand All @@ -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)
Expand Down Expand Up @@ -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 */
Expand All @@ -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:
Expand Down
34 changes: 25 additions & 9 deletions src/tests/concurrent.c
Expand Up @@ -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 },
Expand All @@ -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");
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand Down

0 comments on commit 3d67411

Please sign in to comment.