Merge pull request #2089 from brauner/2018-01-17/restore_blocking_wait

lxccontainer: restore blocking wait()
This commit is contained in:
Serge Hallyn 2018-01-17 17:44:24 -06:00 committed by GitHub
commit dc4f8fb11a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 141 additions and 53 deletions

View File

@ -93,6 +93,7 @@ static const char *lxc_cmd_str(lxc_cmd_t cmd)
[LXC_CMD_GET_LXCPATH] = "get_lxcpath",
[LXC_CMD_ADD_STATE_CLIENT] = "add_state_client",
[LXC_CMD_CONSOLE_LOG] = "console_log",
[LXC_CMD_SERVE_STATE_CLIENTS] = "serve_state_clients",
};
if (cmd >= LXC_CMD_MAX)
@ -859,6 +860,7 @@ int lxc_cmd_add_state_client(const char *name, const char *lxcpath,
return STOPPED;
if (ret < 0) {
if (errno != ECONNREFUSED)
ERROR("%s - Failed to execute command", strerror(errno));
return -1;
}
@ -1055,6 +1057,51 @@ out:
return lxc_cmd_rsp_send(fd, &rsp);
}
int lxc_cmd_serve_state_clients(const char *name, const char *lxcpath,
lxc_state_t state)
{
int stopped;
ssize_t ret;
struct lxc_cmd_rr cmd = {
.req = {
.cmd = LXC_CMD_SERVE_STATE_CLIENTS,
.data = INT_TO_PTR(state)
},
};
ret = lxc_cmd(name, &cmd, &stopped, lxcpath, NULL);
if (ret < 0) {
ERROR("%s - Failed to execute command", strerror(errno));
return -1;
}
return 0;
}
static int lxc_cmd_serve_state_clients_callback(int fd, struct lxc_cmd_req *req,
struct lxc_handler *handler)
{
int ret;
lxc_state_t state = PTR_TO_INT(req->data);
struct lxc_cmd_rsp rsp = {0};
ret = lxc_serve_state_clients(handler->name, handler, state);
if (ret < 0)
goto reap_client_fd;
ret = lxc_cmd_rsp_send(fd, &rsp);
if (ret < 0)
goto reap_client_fd;
return 0;
reap_client_fd:
/* Special indicator to lxc_cmd_handler() to close the fd and do related
* cleanup.
*/
return 1;
}
static int lxc_cmd_process(int fd, struct lxc_cmd_req *req,
struct lxc_handler *handler)
{
@ -1073,6 +1120,7 @@ static int lxc_cmd_process(int fd, struct lxc_cmd_req *req,
[LXC_CMD_GET_LXCPATH] = lxc_cmd_get_lxcpath_callback,
[LXC_CMD_ADD_STATE_CLIENT] = lxc_cmd_add_state_client_callback,
[LXC_CMD_CONSOLE_LOG] = lxc_cmd_console_log_callback,
[LXC_CMD_SERVE_STATE_CLIENTS] = lxc_cmd_serve_state_clients_callback,
};
if (req->cmd >= LXC_CMD_MAX) {

View File

@ -50,6 +50,7 @@ typedef enum {
LXC_CMD_GET_LXCPATH,
LXC_CMD_ADD_STATE_CLIENT,
LXC_CMD_CONSOLE_LOG,
LXC_CMD_SERVE_STATE_CLIENTS,
LXC_CMD_MAX,
} lxc_cmd_t;
@ -116,6 +117,8 @@ extern int lxc_cmd_stop(const char *name, const char *lxcpath);
extern int lxc_cmd_add_state_client(const char *name, const char *lxcpath,
lxc_state_t states[MAX_STATE],
int *state_client_fd);
extern int lxc_cmd_serve_state_clients(const char *name, const char *lxcpath,
lxc_state_t state);
struct lxc_epoll_descr;
struct lxc_handler;

View File

@ -31,57 +31,74 @@
#include <sys/types.h>
#include <sys/param.h>
#include "commands.h"
#include "error.h"
#include "state.h"
#include "monitor.h"
#include "log.h"
#include "lxc.h"
#include "monitor.h"
#include "parse.h"
#include "state.h"
lxc_log_define(lxc_freezer, lxc);
lxc_state_t freezer_state(const char *name, const char *lxcpath)
{
int ret;
char v[100];
if (lxc_cgroup_get("freezer.state", v, 100, name, lxcpath) < 0)
ret = lxc_cgroup_get("freezer.state", v, sizeof(v), name, lxcpath);
if (ret < 0)
return -1;
if (v[strlen(v)-1] == '\n')
v[strlen(v)-1] = '\0';
v[99] = '\0';
v[lxc_char_right_gc(v, strlen(v))] = '\0';
return lxc_str2state(v);
}
static int do_freeze_thaw(int freeze, const char *name, const char *lxcpath)
static int do_freeze_thaw(bool freeze, const char *name, const char *lxcpath)
{
int ret;
char v[100];
const char *state = freeze ? "FROZEN" : "THAWED";
size_t state_len = 6;
lxc_state_t new_state = freeze ? FROZEN : THAWED;
if (lxc_cgroup_set("freezer.state", state, name, lxcpath) < 0) {
ERROR("Failed to freeze %s:%s", lxcpath, name);
ret = lxc_cgroup_set("freezer.state", state, name, lxcpath);
if (ret < 0) {
ERROR("Failed to freeze %s", name);
return -1;
}
while (1) {
if (lxc_cgroup_get("freezer.state", v, 100, name, lxcpath) < 0) {
ERROR("Failed to get new freezer state for %s:%s", lxcpath, name);
for (;;) {
ret = lxc_cgroup_get("freezer.state", v, sizeof(v), name, lxcpath);
if (ret < 0) {
ERROR("Failed to get freezer state of %s", name);
return -1;
}
if (v[strlen(v)-1] == '\n')
v[strlen(v)-1] = '\0';
if (strncmp(v, state, strlen(state)) == 0) {
if (name)
lxc_monitor_send_state(name, freeze ? FROZEN : THAWED, lxcpath);
v[99] = '\0';
v[lxc_char_right_gc(v, strlen(v))] = '\0';
ret = strncmp(v, state, state_len);
if (ret == 0) {
lxc_cmd_serve_state_clients(name, lxcpath, new_state);
lxc_monitor_send_state(name, new_state, lxcpath);
return 0;
}
sleep(1);
}
}
int lxc_freeze(const char *name, const char *lxcpath)
{
lxc_cmd_serve_state_clients(name, lxcpath, FREEZING);
lxc_monitor_send_state(name, FREEZING, lxcpath);
return do_freeze_thaw(1, name, lxcpath);
return do_freeze_thaw(true, name, lxcpath);
}
int lxc_unfreeze(const char *name, const char *lxcpath)
{
return do_freeze_thaw(0, name, lxcpath);
return do_freeze_thaw(false, name, lxcpath);
}

View File

@ -349,8 +349,7 @@ static int signal_handler(int fd, uint32_t events, void *data,
return LXC_MAINLOOP_CLOSE;
}
static int lxc_serve_state_clients(const char *name,
struct lxc_handler *handler,
int lxc_serve_state_clients(const char *name, struct lxc_handler *handler,
lxc_state_t state)
{
ssize_t ret;
@ -359,7 +358,11 @@ static int lxc_serve_state_clients(const char *name,
struct lxc_msg msg = {.type = lxc_msg_state, .value = state};
process_lock();
if (state == THAWED)
handler->state = RUNNING;
else
handler->state = state;
TRACE("Set container state to %s", lxc_state2str(state));
if (lxc_list_empty(&handler->conf->state_clients)) {

View File

@ -117,7 +117,11 @@ struct lxc_operations {
};
extern int lxc_poll(const char *name, struct lxc_handler *handler);
extern int lxc_set_state(const char *name, struct lxc_handler *handler, lxc_state_t state);
extern int lxc_set_state(const char *name, struct lxc_handler *handler,
lxc_state_t state);
extern int lxc_serve_state_clients(const char *name,
struct lxc_handler *handler,
lxc_state_t state);
extern void lxc_abort(const char *name, struct lxc_handler *handler);
extern struct lxc_handler *lxc_init_handler(const char *name,
struct lxc_conf *conf,

View File

@ -115,13 +115,26 @@ extern int lxc_wait(const char *lxcname, const char *states, int timeout,
if (fillwaitedstates(states, s))
return -1;
for (;;) {
state = lxc_cmd_sock_get_state(lxcname, lxcpath, s, timeout);
if (state < 0) {
SYSERROR("failed to receive state from monitor");
if (state >= 0)
break;
if (errno != ECONNREFUSED) {
SYSERROR("Failed to receive state from monitor");
return -1;
}
TRACE("retrieved state of container %s", lxc_state2str(state));
if (timeout > 0)
timeout--;
if (timeout == 0)
return -1;
sleep(1);
}
TRACE("Retrieved state of container %s", lxc_state2str(state));
if (!s[state])
return -1;