Commit 2acf7795 by Dwight Engen Committed by Serge Hallyn

fix memory leaks in cgroup functions

There were several memory leaks in the cgroup functions, notably in the success cases. The cgpath test program was refactored and additional tests added to it. It was used in various modes under valgrind to test that the leaks were fixed. Simplify lxc_cgroup_path_get() and cgroup_path_get by having them return a char * instead of an int and an output char * argument. The only return values ever used were -1 and 0, which are now handled with NULL and non-NULL returns respectively. Use consistent variable names of cgabspath when refering to an absolute path to a cgroup subsystem or file, and cgrelpath when refering to a container "group/name" within the cgroup heirarchy. Remove unused subsystem argument to lxc_cmd_get_cgroup_path(). Remove unused #define MAXPRIOLEN Make template arg to lxcapi_create() const Signed-off-by: 's avatarDwight Engen <dwight.engen@oracle.com> Signed-off-by: 's avatarSerge Hallyn <serge.hallyn@ubuntu.com>
parent 6a44839f
......@@ -23,15 +23,13 @@
#ifndef _cgroup_h
#define _cgroup_h
#define MAXPRIOLEN 24
struct lxc_handler;
extern int lxc_cgroup_destroy(const char *cgpath);
extern int lxc_cgroup_path_get(char **path, const char *subsystem, const char *name,
extern char *lxc_cgroup_path_get(const char *subsystem, const char *name,
const char *lxcpath);
extern int lxc_cgroup_nrtasks(const char *cgpath);
extern char *lxc_cgroup_path_create(const char *lxcgroup, const char *name);
extern int lxc_cgroup_enter(const char *cgpath, pid_t pid);
extern int lxc_cgroup_attach(pid_t pid, const char *name, const char *lxcpath);
extern int cgroup_path_get(char **path, const char *subsystem, const char *cgpath);
extern char *cgroup_path_get(const char *subsystem, const char *cgpath);
#endif
......@@ -335,15 +335,13 @@ static int lxc_cmd_get_clone_flags_callback(int fd, struct lxc_cmd_req *req,
* particular subsystem. This is the cgroup path relative to the root
* of the cgroup filesystem.
*
* @subsystem : the cgroup subsystem of interest (i.e. freezer)
* @name : name of container to connect to
* @lxcpath : the lxcpath in which the container is running
*
* Returns the path on success, NULL on failure. The caller must free() the
* returned path.
*/
char *lxc_cmd_get_cgroup_path(const char *subsystem, const char *name,
const char *lxcpath)
char *lxc_cmd_get_cgroup_path(const char *name, const char *lxcpath)
{
int ret, stopped = 0;
struct lxc_cmd_rr cmd = {
......
......@@ -67,8 +67,7 @@ struct lxc_cmd_console_rsp_data {
extern int lxc_cmd_console(const char *name, int *ttynum, int *fd,
const char *lxcpath);
extern char *lxc_cmd_get_cgroup_path(const char *subsystem,
const char *name, const char *lxcpath);
extern char *lxc_cmd_get_cgroup_path(const char *name, const char *lxcpath);
extern int lxc_cmd_get_clone_flags(const char *name, const char *lxcpath);
extern char *lxc_cmd_get_config_item(const char *name, const char *item, const char *lxcpath);
extern pid_t lxc_cmd_get_init_pid(const char *name, const char *lxcpath);
......
......@@ -120,19 +120,16 @@ out:
static int freeze_unfreeze(const char *name, int freeze, const char *lxcpath)
{
char *nsgroup = NULL;
char *cgabspath;
int ret;
ret = lxc_cgroup_path_get(&nsgroup, "freezer", name, lxcpath);
if (ret)
goto fail;
return do_unfreeze(nsgroup, freeze, name, lxcpath);
fail:
if (nsgroup)
free(nsgroup);
cgabspath = lxc_cgroup_path_get("freezer", name, lxcpath);
if (!cgabspath)
return -1;
ret = do_unfreeze(cgabspath, freeze, name, lxcpath);
free(cgabspath);
return ret;
}
int lxc_freeze(const char *name, const char *lxcpath)
......@@ -146,19 +143,16 @@ int lxc_unfreeze(const char *name, const char *lxcpath)
return freeze_unfreeze(name, 0, lxcpath);
}
int lxc_unfreeze_bypath(const char *cgpath)
int lxc_unfreeze_bypath(const char *cgrelpath)
{
char *nsgroup = NULL;
char *cgabspath;
int ret;
ret = cgroup_path_get(&nsgroup, "freezer", cgpath);
if (ret)
goto fail;
return do_unfreeze(nsgroup, 0, NULL, NULL);
fail:
if (nsgroup)
free(nsgroup);
cgabspath = cgroup_path_get("freezer", cgrelpath);
if (!cgabspath)
return -1;
ret = do_unfreeze(cgabspath, 0, NULL, NULL);
free(cgabspath);
return ret;
}
......@@ -555,7 +555,7 @@ static bool create_container_dir(struct lxc_container *c)
* for ->create, argv contains the arguments to pass to the template,
* terminated by NULL. If no arguments, you can just pass NULL.
*/
static bool lxcapi_create(struct lxc_container *c, char *t, char *const argv[])
static bool lxcapi_create(struct lxc_container *c, const char *t, char *const argv[])
{
bool bret = false;
pid_t pid;
......@@ -621,7 +621,7 @@ static bool lxcapi_create(struct lxc_container *c, char *t, char *const argv[])
newargv = malloc(nargs * sizeof(*newargv));
if (!newargv)
exit(1);
newargv[0] = t;
newargv[0] = (char *)t;
len = strlen(c->config_path) + strlen(c->name) + strlen("--path=") + 2;
patharg = malloc(len);
......@@ -702,7 +702,7 @@ static bool lxcapi_shutdown(struct lxc_container *c, int timeout)
return retv;
}
static bool lxcapi_createl(struct lxc_container *c, char *t, ...)
static bool lxcapi_createl(struct lxc_container *c, const char *t, ...)
{
bool bret = false;
char **args = NULL, **temp;
......
......@@ -48,8 +48,8 @@ struct lxc_container {
bool (*set_config_item)(struct lxc_container *c, const char *key, const char *value);
bool (*destroy)(struct lxc_container *c);
bool (*save_config)(struct lxc_container *c, const char *alt_file);
bool (*create)(struct lxc_container *c, char *t, char *const argv[]);
bool (*createl)(struct lxc_container *c, char *t, ...);
bool (*create)(struct lxc_container *c, const char *t, char *const argv[]);
bool (*createl)(struct lxc_container *c, const char *t, ...);
/* send SIGPWR. if timeout is not 0 or -1, do a hard stop after timeout seconds */
bool (*shutdown)(struct lxc_container *c, int timeout);
/* clear all network or capability items in the in-memory configuration */
......
......@@ -69,38 +69,40 @@ lxc_state_t lxc_str2state(const char *state)
static lxc_state_t freezer_state(const char *name, const char *lxcpath)
{
char *nsgroup = NULL;
char *cgabspath = NULL;
char freezer[MAXPATHLEN];
char status[MAXPATHLEN];
FILE *file;
int err;
int ret;
err = lxc_cgroup_path_get(&nsgroup, "freezer", name, lxcpath);
if (err)
goto fail;
cgabspath = lxc_cgroup_path_get("freezer", name, lxcpath);
if (!cgabspath)
return -1;
err = snprintf(freezer, MAXPATHLEN, "%s/freezer.state", nsgroup);
if (err < 0 || err >= MAXPATHLEN)
goto fail;
ret = snprintf(freezer, MAXPATHLEN, "%s/freezer.state", cgabspath);
if (ret < 0 || ret >= MAXPATHLEN)
goto out;
file = fopen(freezer, "r");
if (!file)
goto fail;
if (!file) {
ret = -1;
goto out;
}
err = fscanf(file, "%s", status);
ret = fscanf(file, "%s", status);
fclose(file);
if (err == EOF) {
if (ret == EOF) {
SYSERROR("failed to read %s", freezer);
goto fail;
ret = -1;
goto out;
}
return lxc_str2state(status);
ret = lxc_str2state(status);
fail:
if (nsgroup)
free(nsgroup);
return -1;
out:
free(cgabspath);
return ret;
}
lxc_state_t lxc_getstate(const char *name, const char *lxcpath)
......
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