Skip to content

Commit

Permalink
Merge pull request #1810 from brauner/2017-09-12/start_move_env_setup
Browse files Browse the repository at this point in the history
start: pass LXC_LOG_LEVEL to hooks
  • Loading branch information
stgraber committed Sep 18, 2017
2 parents dbac6c0 + 8bd8018 commit 329414e
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 92 deletions.
2 changes: 2 additions & 0 deletions doc/lxc.container.conf.sgml.in
Expand Up @@ -1446,6 +1446,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
<listitem><para> LXC_CONFIG_FILE: the path to the container configuration file. </para></listitem>
<listitem><para> LXC_SRC_NAME: in the case of the clone hook, this is the original container's name. </para></listitem>
<listitem><para> LXC_ROOTFS_PATH: this is the lxc.rootfs.path entry for the container. Note this is likely not where the mounted rootfs is to be found, use LXC_ROOTFS_MOUNT for that. </para></listitem>
<listitem><para> LXC_CGNS_AWARE: indicated whether the container is cgroup namespace aware. </para></listitem>
<listitem><para> LXC_LOG_LEVEL: the container's log level. </para></listitem>
</itemizedlist>
</para>
<para>
Expand Down
3 changes: 3 additions & 0 deletions src/lxc/start.c
Expand Up @@ -631,6 +631,9 @@ int lxc_init(const char *name, struct lxc_handler *handler)

if (setenv("LXC_CGNS_AWARE", "1", 1))
SYSERROR("Failed to set environment variable LXC_CGNS_AWARE=1.");

if (setenv("LXC_LOG_LEVEL", lxc_log_priority_to_string(handler->conf->loglevel), 1))
SYSERROR("Failed to set environment variable LXC_CGNS_AWARE=1.");
/* End of environment variable setup for hooks. */

TRACE("set environment variables");
Expand Down
154 changes: 62 additions & 92 deletions src/lxc/utils.c
Expand Up @@ -470,135 +470,105 @@ const char** lxc_va_arg_list_to_argv_const(va_list ap, size_t skip)
return (const char**)lxc_va_arg_list_to_argv(ap, skip, 0);
}

extern struct lxc_popen_FILE *lxc_popen(const char *command)
struct lxc_popen_FILE *lxc_popen(const char *command)
{
struct lxc_popen_FILE *fp = NULL;
int parent_end = -1, child_end = -1;
int ret;
int pipe_fds[2];
pid_t child_pid;
struct lxc_popen_FILE *fp = NULL;

int r = pipe2(pipe_fds, O_CLOEXEC);

if (r < 0) {
ERROR("pipe2 failure");
ret = pipe2(pipe_fds, O_CLOEXEC);
if (ret < 0)
return NULL;
}

parent_end = pipe_fds[0];
child_end = pipe_fds[1];

child_pid = fork();
if (child_pid < 0)
goto on_error;

if (child_pid == 0) {
/* child */
int child_std_end = STDOUT_FILENO;

close(parent_end);
if (!child_pid) {
sigset_t mask;

if (child_end != child_std_end) {
/* dup2() doesn't dup close-on-exec flag */
dup2(child_end, child_std_end);
close(pipe_fds[0]);

/* it's safe not to close child_end here
* as it's marked close-on-exec anyway
*/
} else {
/*
* The descriptor is already the one we will use.
* But it must not be marked close-on-exec.
* Undo the effects.
*/
if (fcntl(child_end, F_SETFD, 0) != 0) {
SYSERROR("Failed to remove FD_CLOEXEC from fd.");
exit(127);
}
}

/*
* Unblock signals.
* This is the main/only reason
* why we do our lousy popen() emulation.
*/
{
sigset_t mask;
sigfillset(&mask);
sigprocmask(SIG_UNBLOCK, &mask, NULL);
/* duplicate stdout */
if (pipe_fds[1] != STDOUT_FILENO)
ret = dup2(pipe_fds[1], STDOUT_FILENO);
else
ret = fcntl(pipe_fds[1], F_SETFD, 0);
if (ret < 0) {
close(pipe_fds[1]);
exit(EXIT_FAILURE);
}

execl("/bin/sh", "sh", "-c", command, (char *) NULL);
exit(127);
}
/* duplicate stderr */
if (pipe_fds[1] != STDERR_FILENO)
ret = dup2(pipe_fds[1], STDERR_FILENO);
else
ret = fcntl(pipe_fds[1], F_SETFD, 0);
close(pipe_fds[1]);
if (ret < 0)
exit(EXIT_FAILURE);

/* parent */
/* unblock all signals */
ret = sigfillset(&mask);
if (ret < 0)
exit(EXIT_FAILURE);

close(child_end);
ret = sigprocmask(SIG_UNBLOCK, &mask, NULL);
if (ret < 0)
exit(EXIT_FAILURE);

if (child_pid < 0) {
ERROR("fork failure");
goto error;
execl("/bin/sh", "sh", "-c", command, (char *)NULL);
exit(127);
}

fp = calloc(1, sizeof(*fp));
if (!fp) {
ERROR("failed to allocate memory");
goto error;
}
close(pipe_fds[1]);
pipe_fds[1] = -1;

fp->f = fdopen(parent_end, "r");
if (!fp->f) {
ERROR("fdopen failure");
goto error;
}
fp = malloc(sizeof(*fp));
if (!fp)
goto on_error;

fp->child_pid = child_pid;
fp->pipe = pipe_fds[0];

return fp;

error:
fp->f = fdopen(pipe_fds[0], "r");
if (!fp->f)
goto on_error;

if (fp) {
if (fp->f) {
fclose(fp->f);
parent_end = -1; /* so we do not close it second time */
}
return fp;

on_error:
if (fp)
free(fp);
}

if (parent_end != -1)
close(parent_end);
if (pipe_fds[0] >= 0)
close(pipe_fds[0]);

if (pipe_fds[1] >= 0)
close(pipe_fds[1]);

return NULL;
}

extern int lxc_pclose(struct lxc_popen_FILE *fp)
int lxc_pclose(struct lxc_popen_FILE *fp)
{
FILE *f = NULL;
pid_t child_pid = 0;
int wstatus = 0;
pid_t wait_pid;
int wstatus = 0;

if (fp) {
f = fp->f;
child_pid = fp->child_pid;
/* free memory (we still need to close file stream) */
free(fp);
fp = NULL;
}

if (!f || fclose(f)) {
ERROR("fclose failure");
if (!fp)
return -1;
}

do {
wait_pid = waitpid(child_pid, &wstatus, 0);
} while (wait_pid == -1 && errno == EINTR);
wait_pid = waitpid(fp->child_pid, &wstatus, 0);
} while (wait_pid < 0 && errno == EINTR);

if (wait_pid == -1) {
ERROR("waitpid failure");
close(fp->pipe);
fclose(fp->f);
free(fp);

if (wait_pid < 0)
return -1;
}

return wstatus;
}
Expand Down
1 change: 1 addition & 0 deletions src/lxc/utils.h
Expand Up @@ -190,6 +190,7 @@ static inline int signalfd(int fd, const sigset_t *mask, int flags)
* without additional wrappers.
*/
struct lxc_popen_FILE {
int pipe;
FILE *f;
pid_t child_pid;
};
Expand Down

0 comments on commit 329414e

Please sign in to comment.