Fix LXC.list_containers to release GIL

This commit is contained in:
John Keiser 2014-03-25 13:20:20 -07:00 committed by Andre Nathan
parent acc636b1c8
commit 8514f53b99
2 changed files with 47 additions and 26 deletions

View file

@ -162,6 +162,29 @@ lxc_version(VALUE self)
return rb_str_new2(lxc_get_version()); return rb_str_new2(lxc_get_version());
} }
struct list_containers_outside_gil_args
{
int active;
int defined;
char *config;
char **names;
};
static VALUE
list_containers_outside_gil(void *args_void)
{
struct list_containers_outside_gil_args *args = (struct list_containers_outside_gil_args *)args_void;
int num_containers = 0;
args->names = NULL;
if (args->active && args->defined)
num_containers = list_all_containers(args->config, &args->names, NULL);
else if (args->active)
num_containers = list_active_containers(args->config, &args->names, NULL);
else if (args->defined)
num_containers = list_defined_containers(args->config, &args->names, NULL);
return INT2NUM(num_containers);
}
/* /*
* call-seq: * call-seq:
* LXC.list_containers([opts]) * LXC.list_containers([opts])
@ -176,36 +199,33 @@ static VALUE
lxc_list_containers(int argc, VALUE *argv, VALUE self) lxc_list_containers(int argc, VALUE *argv, VALUE self)
{ {
int i, num_containers; int i, num_containers;
int active, defined;
char *config;
char **names;
VALUE rb_active, rb_defined, rb_config; VALUE rb_active, rb_defined, rb_config;
VALUE rb_opts; VALUE rb_opts;
VALUE rb_containers; VALUE rb_containers;
struct list_containers_outside_gil_args args;
rb_scan_args(argc, argv, "01", &rb_opts); rb_scan_args(argc, argv, "01", &rb_opts);
if (NIL_P(rb_opts)) { args.active = 1;
active = 1; args.defined = 1;
defined = 1; args.config = NULL;
config = NULL;
} else {
Check_Type(rb_opts, T_HASH);
rb_active = rb_hash_aref(rb_opts, SYMBOL("active"));
active = (rb_active != Qnil) && (rb_active != Qfalse);
rb_defined = rb_hash_aref(rb_opts, SYMBOL("defined"));
defined = (rb_defined != Qnil) && (rb_defined != Qfalse);
rb_config = rb_hash_aref(rb_opts, SYMBOL("config_path"));
config = NIL_P(rb_config) ? NULL : StringValuePtr(rb_config);
}
num_containers = 0; if (!NIL_P(rb_opts)) {
if (active && defined) Check_Type(rb_opts, T_HASH);
num_containers = list_all_containers(config, &names, NULL);
else if (active) rb_active = rb_hash_aref(rb_opts, SYMBOL("active"));
num_containers = list_active_containers(config, &names, NULL); if (!NIL_P(rb_active))
else if (defined) args.active = rb_active != Qfalse;
num_containers = list_defined_containers(config, &names, NULL);
rb_defined = rb_hash_aref(rb_opts, SYMBOL("defined"));
if (!NIL_P(rb_defined))
args.defined = rb_defined != Qfalse;
rb_config = rb_hash_aref(rb_opts, SYMBOL("config_path"));
if (!NIL_P(rb_config))
args.config = StringValuePtr(rb_config);
}
num_containers = NUM2INT(rb_thread_blocking_region(list_containers_outside_gil, &args, NULL, NULL));
if (num_containers < 0) if (num_containers < 0)
rb_raise(Error, "failure to list containers"); rb_raise(Error, "failure to list containers");
@ -215,10 +235,10 @@ lxc_list_containers(int argc, VALUE *argv, VALUE self)
* ie, don't use free_c_string_array(). * ie, don't use free_c_string_array().
*/ */
for (i = 0; i < num_containers; i++) { for (i = 0; i < num_containers; i++) {
rb_ary_store(rb_containers, i, rb_str_new2(names[i])); rb_ary_store(rb_containers, i, rb_str_new2(args.names[i]));
free(names[i]); free(args.names[i]);
} }
free(names); free(args.names);
return rb_containers; return rb_containers;
} }

View file

@ -45,6 +45,7 @@ class TestLXCCreated < Test::Unit::TestCase
end end
def test_container_rename def test_container_rename
@container.stop if @container.running?
renamed = @container.rename(@new_name) renamed = @container.rename(@new_name)
assert_equal(@new_name, renamed.name) assert_equal(@new_name, renamed.name)
rerenamed = renamed.rename(@name) rerenamed = renamed.rename(@name)