[lxc-devel] [PATCH 1/2] fix trivial off by one error

Dwight Engen dwight.engen at oracle.com
Wed Sep 19 14:45:25 UTC 2012


On Tue, 18 Sep 2012 14:32:02 -0700 (PDT)
Christian Seiler <christian at iwakd.de> wrote:

> Hi,
> 
> > Do you think mallocing an fd_set and using FD_SET() and friends
> > would be better? The (dispose|finish) loops would visit FD_SETSIZE
> > bits with an FD_ISSET() test, which is more work than you have
> > currently with the early out, but we would probably save on the
> > initialization with FD_ZERO(). I don't know if
> > lxc_cgroup_(dispose|finish)_attach is performance critical.
> 
> I don't think performance is that much of an issue here, but to me it
> seems that using fd_set logic would complicate things quite a bit
> unnecessarily. The current logic is already a bit complicated because
> the cgroup task files have to be opened before setns() but written to
> only after the fork() call when we know the pid which happens after
> setns(). Having a simple array with a loop over it appears to be much
> more straight-forward to me, especially since iterating over an fd_set
> is kind of convoluted.
> 
> > Or I can just add a comment :)
> 
> My suggestion would be to do just that unless someone has a good
> reason to change the current logic.
> 
> All IMHO of course, I just wrote the initial patch, in the end other
> people get to decide what goes in. ;-)
> 
> Regards,
> Christian

Just to make clear what I was suggesting, here is a patch. It may not
be any better/clearer than the original code, its less storage (1024
bytes vs 128) and handles more fd's (not that there will ever be that
many), but its more code.

diff --git a/src/lxc/cgroup.c b/src/lxc/cgroup.c
index a02ebc2..63eac93 100644
--- a/src/lxc/cgroup.c
+++ b/src/lxc/cgroup.c
@@ -31,6 +31,7 @@
 #include <dirent.h>
 #include <fcntl.h>
 #include <sys/types.h>
+#include <sys/select.h>
 #include <sys/stat.h>
 #include <sys/param.h>
 #include <sys/inotify.h>
@@ -322,8 +323,8 @@ static int lxc_one_cgroup_attach(const char *name, struct mntent *mntent, pid_t
 
 int lxc_cgroup_dispose_attach(void *data)
 {
-	int *fds = data;
-	int ret, err;
+	fd_set *fds = data;
+	int fd, ret, err;
 
 	if (!fds) {
 		return 0;
@@ -331,10 +332,12 @@ int lxc_cgroup_dispose_attach(void *data)
 
 	ret = 0;
 
-	for (; *fds >= 0; fds++) {
-		err = lxc_one_cgroup_dispose_attach(*fds);
-		if (err) {
-			ret = err;
+	for (fd = 0; fd < FD_SETSIZE; fd++) {
+		if (FD_ISSET(fd, fds)) {
+			err = lxc_one_cgroup_dispose_attach(fd);
+			if (err) {
+				ret = err;
+			}
 		}
 	}
 
@@ -345,21 +348,22 @@ int lxc_cgroup_dispose_attach(void *data)
 
 int lxc_cgroup_finish_attach(void *data, pid_t pid)
 {
-	int *fds = data;
-	int err;
+	fd_set *fds = data;
+	int fd, err;
 
 	if (!fds) {
 		return 0;
 	}
 
-	for (; *fds >= 0; fds++) {
-		err = lxc_one_cgroup_finish_attach(*fds, pid);
-		if (err) {
-			/* get rid of the rest of them */
-			lxc_cgroup_dispose_attach(data);
-			return -1;
+	for (fd = 0; fd < FD_SETSIZE; fd++) {
+		if (FD_ISSET(fd, fds)) {
+			err = lxc_one_cgroup_finish_attach(fd, pid);
+			if (err) {
+				/* get rid of the rest of them */
+				lxc_cgroup_dispose_attach(data);
+				return -1;
+			}
 		}
-		*fds = -1;
 	}
 
 	free(data);
@@ -373,9 +377,9 @@ int lxc_cgroup_prepare_attach(const char *name, void **data)
 	FILE *file = NULL;
 	int err = -1;
 	int found = 0;
-	int *fds;
+	int fd;
+	fd_set *fds;
 	int i;
-	static const int MAXFDS = 256;
 
 	file = setmntent(MTAB, "r");
 	if (!file) {
@@ -386,19 +390,17 @@ int lxc_cgroup_prepare_attach(const char *name, void **data)
 	/* create a large enough buffer for all practical
 	 * use cases
 	 */
-	fds = malloc(sizeof(int) * MAXFDS);
+	fds = malloc(sizeof(*fds));
 	if (!fds) {
 		err = -1;
 		goto out;
 	}
-	for (i = 0; i < MAXFDS; i++) {
-		fds[i] = -1;
-	}
+	FD_ZERO(fds);
 
 	err = 0;
 	i = 0;
 	while ((mntent = getmntent(file))) {
-		if (i >= MAXFDS - 1) {
+		if (i >= FD_SETSIZE) {
 			ERROR("too many cgroups to attach to, aborting");
 			lxc_cgroup_dispose_attach(fds);
 			errno = ENOMEM;
@@ -416,12 +418,13 @@ int lxc_cgroup_prepare_attach(const char *name, void **data)
 		INFO("[%d] found cgroup mounted at '%s',opts='%s'",
 		     ++found, mntent->mnt_dir, mntent->mnt_opts);
 
-		fds[i] = lxc_one_cgroup_prepare_attach(name, mntent);
-		if (fds[i] < 0) {
-			err = fds[i];
+		fd = lxc_one_cgroup_prepare_attach(name, mntent);
+		if (fd < 0) {
+			err = fd;
 			lxc_cgroup_dispose_attach(fds);
 			goto out;
 		}
+		FD_SET(fd, fds);
 		i++;
 	};
 




More information about the lxc-devel mailing list