ruby-lxc 1.0.1 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/ext/lxc/extconf.rb CHANGED
@@ -3,5 +3,12 @@ require 'mkmf'
3
3
  abort 'missing liblxc' unless find_library('lxc', 'lxc_container_new')
4
4
  abort 'missing lxc/lxccontainer.h' unless have_header('lxc/lxccontainer.h')
5
5
 
6
+ def add_define(name)
7
+ $defs.push("-D#{name}")
8
+ end
9
+
10
+ add_define "HAVE_RB_THREAD_CALL_WITHOUT_GVL" if have_func('rb_thread_call_without_gvl')
11
+ add_define "HAVE_RB_THREAD_BLOCKING_REGION" if have_func('rb_thread_blocking_region')
12
+
6
13
  $CFLAGS += " -Wall #{ENV['CFLAGS']}"
7
14
  create_makefile('lxc/lxc')
data/ext/lxc/lxc.c CHANGED
@@ -3,13 +3,46 @@
3
3
  #include <linux/sched.h> /* for CLONE_* constants */
4
4
  #include <lxc/lxccontainer.h>
5
5
  #include <lxc/attach_options.h>
6
+ #include <signal.h>
6
7
  #include <stdint.h>
7
8
  #include <string.h>
8
9
 
9
10
  #define SYMBOL(s) ID2SYM(rb_intern(s))
10
11
 
12
+ #if defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL)
13
+ /* Defined in Ruby, but not in all Ruby versions' header files */
14
+ extern void *rb_thread_call_without_gvl(void *(*func)(void *), void *data1,
15
+ rb_unblock_function_t *ubf,
16
+ void *data2);
17
+
18
+ #define RETURN_WITHOUT_GVL_TYPE void *
19
+ #define RETURN_WITHOUT_GVL(x) return (void *)(intptr_t)(x)
20
+ #define RELEASING_GVL(func, arg) \
21
+ (int)(intptr_t)rb_thread_call_without_gvl(func, arg, NULL, NULL)
22
+ #define RELEASING_GVL2(func, arg, killfunc, killarg) \
23
+ (int)(intptr_t)rb_thread_call_without_gvl(func, arg, killfunc, killarg)
24
+ #define RELEASING_GVL_VOID(func, arg) \
25
+ rb_thread_call_without_gvl(func, arg, NULL, NULL)
26
+ #elif defined(HAVE_RB_THREAD_BLOCKING_REGION)
27
+ #define RETURN_WITHOUT_GVL_TYPE VALUE
28
+ #define RETURN_WITHOUT_GVL(x) return INT2NUM(x)
29
+ #define RELEASING_GVL(func, arg) \
30
+ NUM2INT(rb_thread_blocking_region(func, arg, NULL, NULL))
31
+ #define RELEASING_GVL2(func, arg, killfunc, killarg) \
32
+ NUM2INT(rb_thread_blocking_region(func, arg, killfunc, killarg))
33
+ #define RELEASING_GVL_VOID(func, arg) \
34
+ rb_thread_blocking_region(func, arg, NULL, NULL)
35
+ #else
36
+ #define RETURN_WITHOUT_GVL_TYPE int
37
+ #define RETURN_WITHOUT_GVL(x) return x
38
+ #define RELEASING_GVL(func, arg) func(arg)
39
+ #define RELEASING_GVL_VOID(func, arg) func(arg)
40
+ #define RELEASING_GVL2(func, arg, killfunc, killarg) func(arg)
41
+ #endif
42
+
11
43
  extern int lxc_wait_for_pid_status(pid_t pid);
12
44
  extern long lxc_config_parse_arch(const char *arch);
45
+ extern const char *lxc_strerror(int error);
13
46
 
14
47
  static VALUE Container;
15
48
  static VALUE Error;
@@ -161,6 +194,32 @@ lxc_version(VALUE self)
161
194
  return rb_str_new2(lxc_get_version());
162
195
  }
163
196
 
197
+ struct list_containers_without_gvl_args {
198
+ int active;
199
+ int defined;
200
+ char *config;
201
+ char **names;
202
+ };
203
+
204
+ static RETURN_WITHOUT_GVL_TYPE
205
+ list_containers_without_gvl(void *args_void)
206
+ {
207
+ struct list_containers_without_gvl_args *args =
208
+ (struct list_containers_without_gvl_args *)args_void;
209
+ int num_containers = 0;
210
+ args->names = NULL;
211
+ if (args->active && args->defined) {
212
+ num_containers = list_all_containers(args->config, &args->names, NULL);
213
+ } else if (args->active) {
214
+ num_containers =
215
+ list_active_containers(args->config, &args->names, NULL);
216
+ } else if (args->defined) {
217
+ num_containers =
218
+ list_defined_containers(args->config, &args->names, NULL);
219
+ }
220
+ RETURN_WITHOUT_GVL(num_containers);
221
+ }
222
+
164
223
  /*
165
224
  * call-seq:
166
225
  * LXC.list_containers([opts])
@@ -175,36 +234,33 @@ static VALUE
175
234
  lxc_list_containers(int argc, VALUE *argv, VALUE self)
176
235
  {
177
236
  int i, num_containers;
178
- int active, defined;
179
- char *config;
180
- char **names;
181
237
  VALUE rb_active, rb_defined, rb_config;
182
238
  VALUE rb_opts;
183
239
  VALUE rb_containers;
240
+ struct list_containers_without_gvl_args args;
184
241
 
185
242
  rb_scan_args(argc, argv, "01", &rb_opts);
186
243
 
187
- if (NIL_P(rb_opts)) {
188
- active = 1;
189
- defined = 1;
190
- config = NULL;
191
- } else {
244
+ args.active = 1;
245
+ args.defined = 1;
246
+ args.config = NULL;
247
+
248
+ if (!NIL_P(rb_opts)) {
192
249
  Check_Type(rb_opts, T_HASH);
250
+
193
251
  rb_active = rb_hash_aref(rb_opts, SYMBOL("active"));
194
- active = (rb_active != Qnil) && (rb_active != Qfalse);
252
+ if (!NIL_P(rb_active))
253
+ args.active = rb_active != Qfalse;
254
+
195
255
  rb_defined = rb_hash_aref(rb_opts, SYMBOL("defined"));
196
- defined = (rb_defined != Qnil) && (rb_defined != Qfalse);
256
+ if (!NIL_P(rb_defined))
257
+ args.defined = rb_defined != Qfalse;
258
+
197
259
  rb_config = rb_hash_aref(rb_opts, SYMBOL("config_path"));
198
- config = NIL_P(rb_config) ? NULL : StringValuePtr(rb_config);
260
+ if (!NIL_P(rb_config))
261
+ args.config = StringValuePtr(rb_config);
199
262
  }
200
-
201
- num_containers = 0;
202
- if (active && defined)
203
- num_containers = list_all_containers(config, &names, NULL);
204
- else if (active)
205
- num_containers = list_active_containers(config, &names, NULL);
206
- else if (defined)
207
- num_containers = list_defined_containers(config, &names, NULL);
263
+ num_containers = RELEASING_GVL(list_containers_without_gvl, &args);
208
264
  if (num_containers < 0)
209
265
  rb_raise(Error, "failure to list containers");
210
266
 
@@ -214,10 +270,10 @@ lxc_list_containers(int argc, VALUE *argv, VALUE self)
214
270
  * ie, don't use free_c_string_array().
215
271
  */
216
272
  for (i = 0; i < num_containers; i++) {
217
- rb_ary_store(rb_containers, i, rb_str_new2(names[i]));
218
- free(names[i]);
273
+ rb_ary_store(rb_containers, i, rb_str_new2(args.names[i]));
274
+ free(args.names[i]);
219
275
  }
220
- free(names);
276
+ free(args.names);
221
277
 
222
278
  return rb_containers;
223
279
  }
@@ -383,9 +439,27 @@ container_state(VALUE self)
383
439
  return rb_str_intern(rb_funcall(rb_state, rb_intern("downcase"), 0));
384
440
  }
385
441
 
442
+ struct add_device_node_without_gvl_args {
443
+ struct container_data *data;
444
+ char *src_path;
445
+ char *dest_path;
446
+ };
447
+
448
+ static RETURN_WITHOUT_GVL_TYPE
449
+ add_device_node_without_gvl(void *args_void)
450
+ {
451
+ struct add_device_node_without_gvl_args *args =
452
+ (struct add_device_node_without_gvl_args *)args_void;
453
+ RETURN_WITHOUT_GVL(
454
+ args->data->container->add_device_node(args->data->container,
455
+ args->src_path,
456
+ args->dest_path)
457
+ );
458
+ }
459
+
386
460
  /*
387
461
  * call-seq:
388
- * container.add_device_node(src_path, dst_path = src_path)
462
+ * container.add_device_node(src_path, dest_path = src_path)
389
463
  *
390
464
  * Adds a device node to the container.
391
465
  */
@@ -393,17 +467,16 @@ static VALUE
393
467
  container_add_device_node(int argc, VALUE *argv, VALUE self)
394
468
  {
395
469
  int ret;
396
- char *src_path, *dst_path;
397
- struct container_data *data;
398
- VALUE rb_src_path, rb_dst_path;
470
+ VALUE rb_src_path, rb_dest_path;
471
+ struct add_device_node_without_gvl_args args;
399
472
 
400
- rb_scan_args(argc, argv, "11", &rb_src_path, &rb_dst_path);
401
- src_path = NIL_P(rb_src_path) ? NULL : StringValuePtr(rb_src_path);
402
- dst_path = NIL_P(rb_dst_path) ? NULL : StringValuePtr(rb_dst_path);
473
+ rb_scan_args(argc, argv, "11", &rb_src_path, &rb_dest_path);
474
+ args.src_path = StringValuePtr(rb_src_path);
475
+ args.dest_path = NIL_P(rb_dest_path) ? NULL : StringValuePtr(rb_dest_path);
403
476
 
404
- Data_Get_Struct(self, struct container_data, data);
477
+ Data_Get_Struct(self, struct container_data, args.data);
405
478
 
406
- ret = data->container->add_device_node(data->container, src_path, dst_path);
479
+ ret = RELEASING_GVL(add_device_node_without_gvl, &args);
407
480
  if (!ret)
408
481
  rb_raise(Error, "unable to add device node");
409
482
 
@@ -593,6 +666,20 @@ err:
593
666
  return NULL;
594
667
  }
595
668
 
669
+ static RETURN_WITHOUT_GVL_TYPE
670
+ lxc_wait_for_pid_status_without_gvl(void *pid)
671
+ {
672
+ RETURN_WITHOUT_GVL(lxc_wait_for_pid_status(*(pid_t*)pid));
673
+ }
674
+
675
+ #if defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL) || defined(HAVE_RB_THREAD_BLOCKING_REGION)
676
+ static void
677
+ kill_pid_without_gvl(void *pid)
678
+ {
679
+ kill(*(pid_t *)pid, SIGKILL);
680
+ }
681
+ #endif
682
+
596
683
  /*
597
684
  * call-seq:
598
685
  * container.attach(opts = {}, &block)
@@ -650,7 +737,8 @@ container_attach(int argc, VALUE *argv, VALUE self)
650
737
  goto out;
651
738
 
652
739
  if (wait) {
653
- ret = lxc_wait_for_pid_status(pid);
740
+ ret = RELEASING_GVL2(lxc_wait_for_pid_status_without_gvl, &pid,
741
+ kill_pid_without_gvl, &pid);
654
742
  /* handle case where attach fails */
655
743
  if (WIFEXITED(ret) && WEXITSTATUS(ret) == 255)
656
744
  ret = -1;
@@ -702,6 +790,31 @@ container_clear_config_item(VALUE self, VALUE rb_key)
702
790
  return self;
703
791
  }
704
792
 
793
+ struct clone_without_gvl_args {
794
+ struct container_data *data;
795
+ struct lxc_container *new_container;
796
+ char *name;
797
+ char *config_path;
798
+ int flags;
799
+ char *bdev_type;
800
+ char *bdev_data;
801
+ uint64_t new_size;
802
+ char **hook_args;
803
+ };
804
+
805
+ static RETURN_WITHOUT_GVL_TYPE
806
+ clone_without_gvl(void *args_void)
807
+ {
808
+ struct clone_without_gvl_args *args =
809
+ (struct clone_without_gvl_args *)args_void;
810
+ struct lxc_container *container = args->data->container;
811
+ args->new_container =
812
+ container->clone(container, args->name,
813
+ args->config_path, args->flags, args->bdev_type,
814
+ args->bdev_data, args->new_size, args->hook_args);
815
+ RETURN_WITHOUT_GVL(0);
816
+ }
817
+
705
818
  /*
706
819
  * call-seq:
707
820
  * container.clone(clone_name, opts = {})
@@ -719,27 +832,22 @@ container_clear_config_item(VALUE self, VALUE rb_key)
719
832
  static VALUE
720
833
  container_clone(int argc, VALUE *argv, VALUE self)
721
834
  {
722
- int flags;
723
- uint64_t new_size;
724
- char *name, *config_path, *bdev_type, *bdev_data;
725
- char **hook_args;
726
- struct lxc_container *container, *new_container;
727
- struct container_data *data;
728
835
  VALUE rb_name, rb_opts;
729
836
  VALUE rb_flags, rb_config_path, rb_bdev_type, rb_bdev_data;
730
837
  VALUE rb_new_size, rb_hook_args;
731
838
  VALUE rb_args[2];
839
+ struct clone_without_gvl_args args;
732
840
 
733
841
  rb_scan_args(argc, argv, "11", &rb_name, &rb_opts);
734
842
 
735
- name = StringValuePtr(rb_name);
843
+ args.name = StringValuePtr(rb_name);
736
844
 
737
- config_path = NULL;
738
- flags = 0;
739
- bdev_type = NULL;
740
- bdev_data = NULL;
741
- new_size = 0;
742
- hook_args = NULL;
845
+ args.config_path = NULL;
846
+ args.flags = 0;
847
+ args.bdev_type = NULL;
848
+ args.bdev_data = NULL;
849
+ args.new_size = 0;
850
+ args.hook_args = NULL;
743
851
 
744
852
  rb_config_path = Qnil;
745
853
 
@@ -747,49 +855,68 @@ container_clone(int argc, VALUE *argv, VALUE self)
747
855
  Check_Type(rb_opts, T_HASH);
748
856
  rb_config_path = rb_hash_aref(rb_opts, SYMBOL("config_path"));
749
857
  if (!NIL_P(rb_config_path))
750
- config_path = StringValuePtr(rb_config_path);
858
+ args.config_path = StringValuePtr(rb_config_path);
751
859
 
752
860
  rb_flags = rb_hash_aref(rb_opts, SYMBOL("flags"));
753
861
  if (!NIL_P(rb_flags))
754
- flags = NUM2INT(rb_flags);
862
+ args.flags = NUM2INT(rb_flags);
755
863
 
756
864
  rb_bdev_type = rb_hash_aref(rb_opts, SYMBOL("bdev_type"));
757
865
  if (!NIL_P(rb_bdev_type))
758
- bdev_type = StringValuePtr(rb_bdev_type);
866
+ args.bdev_type = StringValuePtr(rb_bdev_type);
759
867
 
760
868
  rb_bdev_data = rb_hash_aref(rb_opts, SYMBOL("bdev_data"));
761
869
  if (!NIL_P(rb_bdev_data))
762
- bdev_data = StringValuePtr(rb_bdev_data);
870
+ args.bdev_data = StringValuePtr(rb_bdev_data);
763
871
 
764
872
  rb_new_size = rb_hash_aref(rb_opts, SYMBOL("new_size"));
765
873
  if (!NIL_P(rb_bdev_data))
766
- new_size = NUM2ULL(rb_new_size);
874
+ args.new_size = NUM2ULL(rb_new_size);
767
875
 
768
876
  rb_hook_args = rb_hash_aref(rb_opts, SYMBOL("hook_args"));
769
877
  if (!NIL_P(rb_hook_args))
770
- hook_args = ruby_to_c_string_array(rb_hook_args);
878
+ args.hook_args = ruby_to_c_string_array(rb_hook_args);
771
879
  }
772
880
 
773
- Data_Get_Struct(self, struct container_data, data);
774
- container = data->container;
881
+ Data_Get_Struct(self, struct container_data, args.data);
775
882
 
776
- new_container = container->clone(container, name, config_path,
777
- flags, bdev_type, bdev_data, new_size,
778
- hook_args);
883
+ RELEASING_GVL_VOID(clone_without_gvl, &args);
779
884
 
780
- if (hook_args)
781
- free_c_string_array(hook_args);
885
+ if (args.hook_args)
886
+ free_c_string_array(args.hook_args);
782
887
 
783
- if (new_container == NULL)
888
+ if (args.new_container == NULL)
784
889
  rb_raise(Error, "unable to clone container");
785
890
 
786
- lxc_container_put(new_container);
891
+ lxc_container_put(args.new_container);
787
892
 
788
893
  rb_args[0] = rb_name;
789
894
  rb_args[1] = rb_config_path;
790
895
  return rb_class_new_instance(2, rb_args, Container);
791
896
  }
792
897
 
898
+ struct console_without_gvl_args {
899
+ struct container_data *data;
900
+ int tty_num;
901
+ int stdin_fd;
902
+ int stdout_fd;
903
+ int stderr_fd;
904
+ int escape;
905
+ };
906
+
907
+ static RETURN_WITHOUT_GVL_TYPE
908
+ console_without_gvl(void *args_void)
909
+ {
910
+ struct console_without_gvl_args *args =
911
+ (struct console_without_gvl_args *)args_void;
912
+ struct lxc_container *container = args->data->container;
913
+ RETURN_WITHOUT_GVL(
914
+ container->console(container, args->tty_num,
915
+ args->stdin_fd, args->stdout_fd,
916
+ args->stderr_fd, args->escape)
917
+ );
918
+ }
919
+
793
920
  /*
794
921
  * call-seq:
795
922
  * container.console(opts = {})
@@ -807,29 +934,44 @@ static VALUE
807
934
  container_console(int argc, VALUE *argv, VALUE self)
808
935
  {
809
936
  int ret;
810
- int tty_num = -1, stdin_fd = 0, stdout_fd = 1, stderr_fd = 2, escape = 1;
811
- struct container_data *data;
812
- struct lxc_container *container;
937
+ struct console_without_gvl_args args;
813
938
  VALUE rb_opts;
939
+ VALUE rb_opt;
940
+
941
+ args.tty_num = -1;
942
+ args.stdin_fd = 0;
943
+ args.stdout_fd = 1;
944
+ args.stderr_fd = 2;
945
+ args.escape = 1;
814
946
 
815
947
  rb_scan_args(argc, argv, "01", &rb_opts);
816
948
  switch (TYPE(rb_opts)) {
817
949
  case T_HASH:
818
- tty_num = NUM2INT(rb_hash_aref(rb_opts, SYMBOL("tty_num")));
819
- stdin_fd = NUM2INT(rb_hash_aref(rb_opts, SYMBOL("stdin_fd")));
820
- stdout_fd = NUM2INT(rb_hash_aref(rb_opts, SYMBOL("stdout_fd")));
821
- stderr_fd = NUM2INT(rb_hash_aref(rb_opts, SYMBOL("stderr_fd")));
822
- escape = NUM2INT(rb_hash_aref(rb_opts, SYMBOL("escape")));
950
+ rb_opt = rb_hash_aref(rb_opts, SYMBOL("tty_num"));
951
+ if (!NIL_P(rb_opt))
952
+ args.tty_num = NUM2INT(rb_opt);
953
+ rb_opt = rb_hash_aref(rb_opts, SYMBOL("stdin_fd"));
954
+ if (!NIL_P(rb_opt))
955
+ args.stdin_fd = NUM2INT(rb_opt);
956
+ rb_opt = rb_hash_aref(rb_opts, SYMBOL("stdout_fd"));
957
+ if (!NIL_P(rb_opt))
958
+ args.stdout_fd = NUM2INT(rb_opt);
959
+ rb_opt = rb_hash_aref(rb_opts, SYMBOL("stderr_fd"));
960
+ if (!NIL_P(rb_opt))
961
+ args.stderr_fd = NUM2INT(rb_opt);
962
+ rb_opt = rb_hash_aref(rb_opts, SYMBOL("escape"));
963
+ if (!NIL_P(rb_opt))
964
+ args.escape = NUM2INT(rb_opt);
965
+ break;
966
+ case T_NIL:
823
967
  break;
824
968
  default:
825
969
  rb_raise(rb_eArgError, "options must be a hash");
826
970
  }
827
971
 
828
- Data_Get_Struct(self, struct container_data, data);
829
- container = data->container;
972
+ Data_Get_Struct(self, struct container_data, args.data);
830
973
 
831
- ret = container->console(container, tty_num, stdin_fd, stdout_fd, stderr_fd,
832
- escape);
974
+ ret = RELEASING_GVL(console_without_gvl, &args);
833
975
  if (ret != 0)
834
976
  rb_raise(Error, "unable to access container console");
835
977
 
@@ -863,6 +1005,27 @@ container_console_fd(int argc, VALUE *argv, VALUE self)
863
1005
  return rb_class_new_instance(1, rb_io_args, rb_cIO);
864
1006
  }
865
1007
 
1008
+ /* Used to run container->create outside of GIL */
1009
+ struct container_create_without_gvl_args {
1010
+ struct container_data *data;
1011
+ char *template;
1012
+ char *bdevtype;
1013
+ int flags;
1014
+ char **args;
1015
+ };
1016
+
1017
+ static RETURN_WITHOUT_GVL_TYPE
1018
+ container_create_without_gvl(void *args_void)
1019
+ {
1020
+ struct container_create_without_gvl_args *args =
1021
+ (struct container_create_without_gvl_args *)args_void;
1022
+ RETURN_WITHOUT_GVL(
1023
+ args->data->container->create(args->data->container, args->template,
1024
+ args->bdevtype, NULL, args->flags,
1025
+ args->args)
1026
+ );
1027
+ }
1028
+
866
1029
  /*
867
1030
  * call-seq:
868
1031
  * container.create(template, bdevtype = nil, flags = 0, args = [])
@@ -876,28 +1039,27 @@ container_console_fd(int argc, VALUE *argv, VALUE self)
876
1039
  static VALUE
877
1040
  container_create(int argc, VALUE *argv, VALUE self)
878
1041
  {
879
- int ret, flags;
880
- char *template;
881
- char *bdevtype;
882
- char **args = { NULL };
883
- struct container_data *data;
884
- struct lxc_container *container;
1042
+ int ret;
885
1043
  VALUE rb_template, rb_bdevtype, rb_flags, rb_args;
1044
+ struct container_create_without_gvl_args args;
1045
+ char **default_args = { NULL };
886
1046
 
887
- rb_scan_args(argc, argv, "13", &rb_template, &rb_bdevtype, &rb_flags, &rb_args);
1047
+ args.args = default_args;
1048
+ rb_scan_args(argc, argv, "13",
1049
+ &rb_template, &rb_bdevtype, &rb_flags, &rb_args);
888
1050
 
889
- template = StringValuePtr(rb_template);
890
- bdevtype = NIL_P(rb_bdevtype) ? NULL : StringValuePtr(rb_bdevtype);
891
- flags = NIL_P(rb_flags) ? 0 : NUM2INT(rb_flags);
1051
+ args.template = StringValuePtr(rb_template);
1052
+ args.bdevtype = NIL_P(rb_bdevtype) ? NULL : StringValuePtr(rb_bdevtype);
1053
+ args.flags = NIL_P(rb_flags) ? 0 : NUM2INT(rb_flags);
892
1054
  if (!NIL_P(rb_args))
893
- args = ruby_to_c_string_array(rb_args);
1055
+ args.args = ruby_to_c_string_array(rb_args);
894
1056
 
895
- Data_Get_Struct(self, struct container_data, data);
896
- container = data->container;
897
- ret = container->create(container, template, bdevtype, NULL, flags, args);
1057
+ Data_Get_Struct(self, struct container_data, args.data);
1058
+
1059
+ ret = RELEASING_GVL(container_create_without_gvl, &args);
898
1060
 
899
1061
  if (!NIL_P(rb_args))
900
- free_c_string_array(args);
1062
+ free_c_string_array(args.args);
901
1063
 
902
1064
  if (!ret)
903
1065
  rb_raise(Error, "unable to create container");
@@ -905,6 +1067,14 @@ container_create(int argc, VALUE *argv, VALUE self)
905
1067
  return self;
906
1068
  }
907
1069
 
1070
+
1071
+ static RETURN_WITHOUT_GVL_TYPE
1072
+ destroy_without_gvl(void *data_void)
1073
+ {
1074
+ struct container_data *data = (struct container_data *)data_void;
1075
+ RETURN_WITHOUT_GVL(data->container->destroy(data->container));
1076
+ }
1077
+
908
1078
  /*
909
1079
  * call-seq:
910
1080
  * container.destroy
@@ -919,12 +1089,19 @@ container_destroy(VALUE self)
919
1089
 
920
1090
  Data_Get_Struct(self, struct container_data, data);
921
1091
 
922
- ret = data->container->destroy(data->container);
1092
+ ret = RELEASING_GVL(destroy_without_gvl, data);
923
1093
  if (!ret)
924
1094
  rb_raise(Error, "unable to destroy container");
925
1095
  return self;
926
1096
  }
927
1097
 
1098
+ static RETURN_WITHOUT_GVL_TYPE
1099
+ freeze_without_gvl(void *data_void)
1100
+ {
1101
+ struct container_data *data = (struct container_data *)data_void;
1102
+ RETURN_WITHOUT_GVL(data->container->freeze(data->container));
1103
+ }
1104
+
928
1105
  /*
929
1106
  * call-seq:
930
1107
  * container.freeze
@@ -939,7 +1116,7 @@ container_freeze(VALUE self)
939
1116
 
940
1117
  Data_Get_Struct(self, struct container_data, data);
941
1118
 
942
- ret = data->container->freeze(data->container);
1119
+ ret = RELEASING_GVL(freeze_without_gvl, data);
943
1120
  if (!ret)
944
1121
  rb_raise(Error, "unable to freeze container");
945
1122
 
@@ -1146,6 +1323,21 @@ container_ips(int argc, VALUE *argv, VALUE self)
1146
1323
  return rb_ips;
1147
1324
  }
1148
1325
 
1326
+ struct load_config_without_gvl_args {
1327
+ struct container_data *data;
1328
+ char *path;
1329
+ };
1330
+
1331
+ static RETURN_WITHOUT_GVL_TYPE
1332
+ load_config_without_gvl(void *args_void)
1333
+ {
1334
+ struct load_config_without_gvl_args *args =
1335
+ (struct load_config_without_gvl_args *)args_void;
1336
+ RETURN_WITHOUT_GVL(
1337
+ args->data->container->load_config(args->data->container, args->path)
1338
+ );
1339
+ }
1340
+
1149
1341
  /*
1150
1342
  * call-seq:
1151
1343
  * container.load_config(config_path = nil)
@@ -1156,22 +1348,28 @@ static VALUE
1156
1348
  container_load_config(int argc, VALUE *argv, VALUE self)
1157
1349
  {
1158
1350
  int ret;
1159
- char *path;
1160
- struct container_data *data;
1161
1351
  VALUE rb_path;
1352
+ struct load_config_without_gvl_args args;
1162
1353
 
1163
1354
  rb_scan_args(argc, argv, "01", &rb_path);
1164
- path = NIL_P(rb_path) ? NULL : StringValuePtr(rb_path);
1355
+ args.path = NIL_P(rb_path) ? NULL : StringValuePtr(rb_path);
1165
1356
 
1166
- Data_Get_Struct(self, struct container_data, data);
1357
+ Data_Get_Struct(self, struct container_data, args.data);
1167
1358
 
1168
- ret = data->container->load_config(data->container, path);
1359
+ ret = RELEASING_GVL(load_config_without_gvl, &args);
1169
1360
  if (!ret)
1170
1361
  rb_raise(Error, "unable to load configuration file");
1171
1362
 
1172
1363
  return self;
1173
1364
  }
1174
1365
 
1366
+ static RETURN_WITHOUT_GVL_TYPE
1367
+ reboot_without_gvl(void* data_void)
1368
+ {
1369
+ struct container_data *data = (struct container_data *)data_void;
1370
+ RETURN_WITHOUT_GVL(data->container->reboot(data->container));
1371
+ }
1372
+
1175
1373
  /*
1176
1374
  * call-seq:
1177
1375
  * container.reboot
@@ -1186,16 +1384,34 @@ container_reboot(VALUE self)
1186
1384
 
1187
1385
  Data_Get_Struct(self, struct container_data, data);
1188
1386
 
1189
- ret = data->container->reboot(data->container);
1387
+ ret = RELEASING_GVL(reboot_without_gvl, data);
1190
1388
  if (!ret)
1191
1389
  rb_raise(Error, "unable to reboot container");
1192
1390
 
1193
1391
  return self;
1194
1392
  }
1195
1393
 
1394
+ struct remove_device_node_without_gvl_args {
1395
+ struct container_data *data;
1396
+ char *src_path;
1397
+ char *dest_path;
1398
+ };
1399
+
1400
+ static RETURN_WITHOUT_GVL_TYPE
1401
+ remove_device_node_without_gvl(void *args_void)
1402
+ {
1403
+ struct remove_device_node_without_gvl_args *args =
1404
+ (struct remove_device_node_without_gvl_args *)args_void;
1405
+ RETURN_WITHOUT_GVL(
1406
+ args->data->container->remove_device_node(args->data->container,
1407
+ args->src_path,
1408
+ args->dest_path)
1409
+ );
1410
+ }
1411
+
1196
1412
  /*
1197
1413
  * call-seq:
1198
- * container.remove_device_node(src_path, dst_path = src_path)
1414
+ * container.remove_device_node(src_path, dest_path = src_path)
1199
1415
  *
1200
1416
  * Removes a device node from the container.
1201
1417
  */
@@ -1203,25 +1419,37 @@ static VALUE
1203
1419
  container_remove_device_node(int argc, VALUE *argv, VALUE self)
1204
1420
  {
1205
1421
  int ret;
1206
- char *src_path, *dst_path;
1207
- struct lxc_container *container;
1208
- struct container_data *data;
1209
- VALUE rb_src_path, rb_dst_path;
1422
+ VALUE rb_src_path, rb_dest_path;
1423
+ struct remove_device_node_without_gvl_args args;
1210
1424
 
1211
- rb_scan_args(argc, argv, "11", &rb_src_path, &rb_dst_path);
1212
- src_path = StringValuePtr(rb_src_path);
1213
- dst_path = NIL_P(rb_dst_path) ? NULL : StringValuePtr(rb_dst_path);
1425
+ rb_scan_args(argc, argv, "11", &rb_src_path, &rb_dest_path);
1426
+ args.src_path = StringValuePtr(rb_src_path);
1427
+ args.dest_path = NIL_P(rb_dest_path) ? NULL : StringValuePtr(rb_dest_path);
1214
1428
 
1215
- Data_Get_Struct(self, struct container_data, data);
1216
- container = data->container;
1429
+ Data_Get_Struct(self, struct container_data, args.data);
1217
1430
 
1218
- ret = container->remove_device_node(container, src_path, dst_path);
1431
+ ret = RELEASING_GVL(remove_device_node_without_gvl, &args);
1219
1432
  if (!ret)
1220
1433
  rb_raise(Error, "unable to remove device node");
1221
1434
 
1222
1435
  return self;
1223
1436
  }
1224
1437
 
1438
+ struct rename_without_gvl_args {
1439
+ struct container_data *data;
1440
+ char *name;
1441
+ };
1442
+
1443
+ static RETURN_WITHOUT_GVL_TYPE
1444
+ rename_without_gvl(void *args_void)
1445
+ {
1446
+ struct rename_without_gvl_args *args =
1447
+ (struct rename_without_gvl_args *)args_void;
1448
+ RETURN_WITHOUT_GVL(
1449
+ args->data->container->rename(args->data->container, args->name)
1450
+ );
1451
+ }
1452
+
1225
1453
  /*
1226
1454
  * call-seq:
1227
1455
  * container.rename(new_name)
@@ -1233,14 +1461,14 @@ static VALUE
1233
1461
  container_rename(VALUE self, VALUE rb_name)
1234
1462
  {
1235
1463
  int ret;
1236
- char *name;
1237
- struct container_data *data;
1238
1464
  VALUE rb_args[2];
1465
+ struct rename_without_gvl_args args;
1239
1466
 
1240
- name = StringValuePtr(rb_name);
1241
- Data_Get_Struct(self, struct container_data, data);
1467
+ Data_Get_Struct(self, struct container_data, args.data);
1468
+
1469
+ args.name = StringValuePtr(rb_name);
1242
1470
 
1243
- ret = data->container->rename(data->container, name);
1471
+ ret = RELEASING_GVL(rename_without_gvl, &args);
1244
1472
  if (!ret)
1245
1473
  rb_raise(Error, "unable to rename container");
1246
1474
 
@@ -1278,20 +1506,34 @@ container_running_config_item(VALUE self, VALUE rb_key)
1278
1506
  return rb_value;
1279
1507
  }
1280
1508
 
1509
+ struct save_config_without_gvl_args {
1510
+ struct container_data *data;
1511
+ char *path;
1512
+ };
1513
+
1514
+ static RETURN_WITHOUT_GVL_TYPE
1515
+ save_config_without_gvl(void *args_void)
1516
+ {
1517
+ struct save_config_without_gvl_args *args =
1518
+ (struct save_config_without_gvl_args *)args_void;
1519
+ RETURN_WITHOUT_GVL(
1520
+ args->data->container->save_config(args->data->container, args->path)
1521
+ );
1522
+ }
1523
+
1281
1524
  static VALUE
1282
1525
  container_save_config(int argc, VALUE *argv, VALUE self)
1283
1526
  {
1284
1527
  int ret;
1285
- char *path;
1286
- struct container_data *data;
1287
1528
  VALUE rb_path;
1529
+ struct save_config_without_gvl_args args;
1288
1530
 
1289
1531
  rb_scan_args(argc, argv, "01", &rb_path);
1290
- path = NIL_P(rb_path) ? NULL : StringValuePtr(rb_path);
1532
+ args.path = NIL_P(rb_path) ? NULL : StringValuePtr(rb_path);
1291
1533
 
1292
- Data_Get_Struct(self, struct container_data, data);
1534
+ Data_Get_Struct(self, struct container_data, args.data);
1293
1535
 
1294
- ret = data->container->save_config(data->container, path);
1536
+ ret = RELEASING_GVL(save_config_without_gvl, &args);
1295
1537
  if (!ret)
1296
1538
  rb_raise(Error, "unable to save configuration file");
1297
1539
 
@@ -1391,6 +1633,21 @@ container_set_config_path(VALUE self, VALUE rb_path)
1391
1633
  return self;
1392
1634
  }
1393
1635
 
1636
+ struct shutdown_without_gvl_args {
1637
+ struct container_data *data;
1638
+ int timeout;
1639
+ };
1640
+
1641
+ static RETURN_WITHOUT_GVL_TYPE
1642
+ shutdown_without_gvl(void* args_void)
1643
+ {
1644
+ struct shutdown_without_gvl_args *args =
1645
+ (struct shutdown_without_gvl_args *)args_void;
1646
+ RETURN_WITHOUT_GVL(
1647
+ args->data->container->shutdown(args->data->container, args->timeout)
1648
+ );
1649
+ }
1650
+
1394
1651
  /*
1395
1652
  * call-seq:
1396
1653
  * container.shutdown(timeout = -1)
@@ -1402,22 +1659,38 @@ container_set_config_path(VALUE self, VALUE rb_path)
1402
1659
  static VALUE
1403
1660
  container_shutdown(int argc, VALUE *argv, VALUE self)
1404
1661
  {
1405
- int ret, timeout;
1406
- struct container_data *data;
1662
+ int ret;
1407
1663
  VALUE rb_timeout;
1664
+ struct shutdown_without_gvl_args args;
1408
1665
 
1409
1666
  rb_scan_args(argc, argv, "01", &rb_timeout);
1410
- timeout = NIL_P(rb_timeout) ? -1 : NUM2INT(rb_timeout);
1411
1667
 
1412
- Data_Get_Struct(self, struct container_data, data);
1668
+ Data_Get_Struct(self, struct container_data, args.data);
1669
+
1670
+ args.timeout = NIL_P(rb_timeout) ? -1 : NUM2INT(rb_timeout);
1413
1671
 
1414
- ret = data->container->shutdown(data->container, timeout);
1672
+ ret = RELEASING_GVL(shutdown_without_gvl, &args);
1415
1673
  if (!ret)
1416
1674
  rb_raise(Error, "unable to shutdown container");
1417
1675
 
1418
1676
  return self;
1419
1677
  }
1420
1678
 
1679
+ struct snapshot_without_gvl_args {
1680
+ struct container_data *data;
1681
+ char *path;
1682
+ };
1683
+
1684
+ static RETURN_WITHOUT_GVL_TYPE
1685
+ snapshot_without_gvl(void* args_void)
1686
+ {
1687
+ struct snapshot_without_gvl_args *args =
1688
+ (struct snapshot_without_gvl_args *)args_void;
1689
+ RETURN_WITHOUT_GVL(
1690
+ args->data->container->snapshot(args->data->container, args->path)
1691
+ );
1692
+ }
1693
+
1421
1694
  /*
1422
1695
  * call-seq:
1423
1696
  * container.snapshot(path = nil)
@@ -1428,17 +1701,16 @@ static VALUE
1428
1701
  container_snapshot(int argc, VALUE *argv, VALUE self)
1429
1702
  {
1430
1703
  int ret;
1431
- char *path;
1432
1704
  char new_name[20];
1433
- struct container_data *data;
1434
1705
  VALUE rb_path;
1706
+ struct snapshot_without_gvl_args args;
1435
1707
 
1436
1708
  rb_scan_args(argc, argv, "01", &rb_path);
1437
- path = NIL_P(rb_path) ? NULL : StringValuePtr(rb_path);
1709
+ args.path = NIL_P(rb_path) ? NULL : StringValuePtr(rb_path);
1438
1710
 
1439
- Data_Get_Struct(self, struct container_data, data);
1711
+ Data_Get_Struct(self, struct container_data, args.data);
1440
1712
 
1441
- ret = data->container->snapshot(data->container, path);
1713
+ ret = RELEASING_GVL(snapshot_without_gvl, &args);
1442
1714
  if (ret < 0)
1443
1715
  rb_raise(Error, "unable to snapshot container");
1444
1716
 
@@ -1449,6 +1721,22 @@ container_snapshot(int argc, VALUE *argv, VALUE self)
1449
1721
  return rb_str_new2(new_name);
1450
1722
  }
1451
1723
 
1724
+ struct snapshot_destroy_without_gvl_args {
1725
+ struct container_data *data;
1726
+ char *name;
1727
+ };
1728
+
1729
+ static RETURN_WITHOUT_GVL_TYPE
1730
+ snapshot_destroy_without_gvl(void *args_void)
1731
+ {
1732
+ struct snapshot_destroy_without_gvl_args *args =
1733
+ (struct snapshot_destroy_without_gvl_args *)args_void;
1734
+ RETURN_WITHOUT_GVL(
1735
+ args->data->container->snapshot_destroy(args->data->container,
1736
+ args->name)
1737
+ );
1738
+ }
1739
+
1452
1740
  /*
1453
1741
  * call-seq:
1454
1742
  * container.snapshot_destroy(name)
@@ -1459,20 +1747,35 @@ static VALUE
1459
1747
  container_snapshot_destroy(VALUE self, VALUE rb_name)
1460
1748
  {
1461
1749
  int ret;
1462
- char *name;
1463
- struct container_data *data;
1750
+ struct snapshot_destroy_without_gvl_args args;
1464
1751
 
1465
- name = StringValuePtr(rb_name);
1752
+ Data_Get_Struct(self, struct container_data, args.data);
1466
1753
 
1467
- Data_Get_Struct(self, struct container_data, data);
1754
+ args.name = StringValuePtr(rb_name);
1468
1755
 
1469
- ret = data->container->snapshot_destroy(data->container, name);
1756
+ ret = RELEASING_GVL(snapshot_destroy_without_gvl, &args);
1470
1757
  if (!ret)
1471
1758
  rb_raise(Error, "unable to destroy snapshot");
1472
1759
 
1473
1760
  return self;
1474
1761
  }
1475
1762
 
1763
+ struct snapshot_list_without_gvl_args {
1764
+ struct container_data *data;
1765
+ struct lxc_snapshot *snapshots;
1766
+ };
1767
+
1768
+ static RETURN_WITHOUT_GVL_TYPE
1769
+ snapshot_list_without_gvl(void *args_void)
1770
+ {
1771
+ struct snapshot_list_without_gvl_args *args =
1772
+ (struct snapshot_list_without_gvl_args *)args_void;
1773
+ RETURN_WITHOUT_GVL(
1774
+ args->data->container->snapshot_list(args->data->container,
1775
+ &args->snapshots)
1776
+ );
1777
+ }
1778
+
1476
1779
  /*
1477
1780
  * call-seq:
1478
1781
  * container.snapshot_list
@@ -1483,30 +1786,47 @@ static VALUE
1483
1786
  container_snapshot_list(VALUE self)
1484
1787
  {
1485
1788
  int i, num_snapshots;
1486
- struct lxc_snapshot *snapshots;
1487
- struct container_data *data;
1488
1789
  VALUE rb_snapshots;
1790
+ struct snapshot_list_without_gvl_args args;
1489
1791
 
1490
- Data_Get_Struct(self, struct container_data, data);
1792
+ Data_Get_Struct(self, struct container_data, args.data);
1491
1793
 
1492
- num_snapshots = data->container->snapshot_list(data->container, &snapshots);
1794
+ num_snapshots = RELEASING_GVL(snapshot_list_without_gvl, &args);
1493
1795
  if (num_snapshots < 0)
1494
1796
  rb_raise(Error, "unable to list snapshots");
1495
1797
 
1496
1798
  rb_snapshots = rb_ary_new2(num_snapshots);
1497
1799
  for (i = 0; i < num_snapshots; i++) {
1498
1800
  VALUE attrs = rb_ary_new2(4);
1499
- rb_ary_store(attrs, 0, rb_str_new2(snapshots[i].name));
1500
- rb_ary_store(attrs, 1, rb_str_new2(snapshots[i].comment_pathname));
1501
- rb_ary_store(attrs, 2, rb_str_new2(snapshots[i].timestamp));
1502
- rb_ary_store(attrs, 3, rb_str_new2(snapshots[i].lxcpath));
1503
- snapshots[i].free(&snapshots[i]);
1801
+ rb_ary_store(attrs, 0, rb_str_new2(args.snapshots[i].name));
1802
+ rb_ary_store(attrs, 1, rb_str_new2(args.snapshots[i].comment_pathname));
1803
+ rb_ary_store(attrs, 2, rb_str_new2(args.snapshots[i].timestamp));
1804
+ rb_ary_store(attrs, 3, rb_str_new2(args.snapshots[i].lxcpath));
1805
+ args.snapshots[i].free(&args.snapshots[i]);
1504
1806
  rb_ary_store(rb_snapshots, i, attrs);
1505
1807
  }
1506
1808
 
1507
1809
  return rb_snapshots;
1508
1810
  }
1509
1811
 
1812
+ struct snapshot_restore_without_gvl_args {
1813
+ struct container_data *data;
1814
+ char *name;
1815
+ char *new_name;
1816
+ };
1817
+
1818
+ static RETURN_WITHOUT_GVL_TYPE
1819
+ snapshot_restore_without_gvl(void *args_void)
1820
+ {
1821
+ struct snapshot_restore_without_gvl_args *args =
1822
+ (struct snapshot_restore_without_gvl_args *)args_void;
1823
+ RETURN_WITHOUT_GVL(
1824
+ args->data->container->snapshot_restore(args->data->container,
1825
+ args->name,
1826
+ args->new_name)
1827
+ );
1828
+ }
1829
+
1510
1830
  /*
1511
1831
  * call-seq:
1512
1832
  * container.snapshot_restore(name, new_name = nil)
@@ -1517,23 +1837,44 @@ static VALUE
1517
1837
  container_snapshot_restore(int argc, VALUE *argv, VALUE self)
1518
1838
  {
1519
1839
  int ret;
1520
- char *name, *new_name;
1521
- struct container_data *data;
1840
+ struct snapshot_restore_without_gvl_args args;
1522
1841
  VALUE rb_name, rb_new_name;
1523
1842
 
1524
1843
  rb_scan_args(argc, argv, "11", &rb_name, &rb_new_name);
1525
- name = StringValuePtr(rb_name);
1526
- new_name = NIL_P(rb_new_name) ? NULL : StringValuePtr(rb_new_name);
1844
+ args.name = StringValuePtr(rb_name);
1845
+ args.new_name = NIL_P(rb_new_name) ? NULL : StringValuePtr(rb_new_name);
1527
1846
 
1528
- Data_Get_Struct(self, struct container_data, data);
1847
+ Data_Get_Struct(self, struct container_data, args.data);
1529
1848
 
1530
- ret = data->container->snapshot_restore(data->container, name, new_name);
1849
+ ret = RELEASING_GVL(snapshot_restore_without_gvl, &args);
1531
1850
  if (!ret)
1532
1851
  rb_raise(Error, "unable to restore snapshot");
1533
1852
 
1534
1853
  return self;
1535
1854
  }
1536
1855
 
1856
+
1857
+ struct start_without_gvl_args {
1858
+ struct container_data *data;
1859
+ int use_init;
1860
+ int daemonize;
1861
+ int close_fds;
1862
+ char **args;
1863
+ };
1864
+
1865
+ static RETURN_WITHOUT_GVL_TYPE
1866
+ start_without_gvl(void *args_void)
1867
+ {
1868
+ struct start_without_gvl_args *args =
1869
+ (struct start_without_gvl_args *)args_void;
1870
+ struct lxc_container *container = args->data->container;
1871
+ container->want_close_all_fds(container, args->close_fds);
1872
+ container->want_daemonize(container, args->daemonize);
1873
+ RETURN_WITHOUT_GVL(
1874
+ container->start(container, args->use_init, args->args)
1875
+ );
1876
+ }
1877
+
1537
1878
  /*
1538
1879
  * call-seq:
1539
1880
  * container.start(opts = {})
@@ -1548,41 +1889,42 @@ container_snapshot_restore(int argc, VALUE *argv, VALUE self)
1548
1889
  static VALUE
1549
1890
  container_start(int argc, VALUE *argv, VALUE self)
1550
1891
  {
1551
- int ret, use_init, daemonize, close_fds;
1552
- char **args;
1553
- struct container_data *data;
1892
+ int ret;
1554
1893
  VALUE rb_use_init, rb_daemonize, rb_close_fds, rb_args, rb_opts;
1894
+ struct start_without_gvl_args args;
1555
1895
 
1556
- use_init = 0;
1557
- daemonize = 1;
1558
- close_fds = 0;
1559
- args = NULL;
1896
+ args.use_init = 0;
1897
+ args.daemonize = 1;
1898
+ args.close_fds = 0;
1899
+ args.args = NULL;
1560
1900
  rb_args = Qnil;
1561
1901
 
1562
1902
  rb_scan_args(argc, argv, "01", &rb_opts);
1563
1903
  if (!NIL_P(rb_opts)) {
1564
1904
  Check_Type(rb_opts, T_HASH);
1565
1905
  rb_use_init = rb_hash_aref(rb_opts, SYMBOL("use_init"));
1566
- use_init = (rb_use_init != Qnil) && (rb_use_init != Qfalse);
1906
+ if (!NIL_P(rb_use_init))
1907
+ args.use_init = (rb_use_init != Qfalse);
1567
1908
 
1568
1909
  rb_daemonize = rb_hash_aref(rb_opts, SYMBOL("daemonize"));
1569
- daemonize = (rb_daemonize != Qnil) && (rb_daemonize != Qfalse);
1910
+ if (!NIL_P(rb_daemonize))
1911
+ args.daemonize = (rb_daemonize != Qfalse);
1570
1912
 
1571
1913
  rb_close_fds = rb_hash_aref(rb_opts, SYMBOL("close_fds"));
1572
- close_fds = (rb_close_fds != Qnil) && (rb_close_fds != Qfalse);
1914
+ if (!NIL_P(rb_close_fds))
1915
+ args.close_fds = (rb_close_fds != Qfalse);
1573
1916
 
1574
1917
  rb_args = rb_hash_aref(rb_opts, SYMBOL("args"));
1575
- args = NIL_P(rb_args) ? NULL : ruby_to_c_string_array(rb_args);
1918
+ if (!NIL_P(rb_args))
1919
+ args.args = ruby_to_c_string_array(rb_args);
1576
1920
  }
1577
1921
 
1578
- Data_Get_Struct(self, struct container_data, data);
1922
+ Data_Get_Struct(self, struct container_data, args.data);
1579
1923
 
1580
- data->container->want_close_all_fds(data->container, close_fds);
1581
- data->container->want_daemonize(data->container, daemonize);
1582
- ret = data->container->start(data->container, use_init, args);
1924
+ ret = RELEASING_GVL(start_without_gvl, &args);
1583
1925
 
1584
1926
  if (!NIL_P(rb_args))
1585
- free_c_string_array(args);
1927
+ free_c_string_array(args.args);
1586
1928
 
1587
1929
  if (!ret)
1588
1930
  rb_raise(Error, "unable to start container");
@@ -1590,6 +1932,13 @@ container_start(int argc, VALUE *argv, VALUE self)
1590
1932
  return self;
1591
1933
  }
1592
1934
 
1935
+ static RETURN_WITHOUT_GVL_TYPE
1936
+ stop_without_gvl(void *data_void)
1937
+ {
1938
+ struct container_data *data = (struct container_data *)data_void;
1939
+ RETURN_WITHOUT_GVL(data->container->stop(data->container));
1940
+ }
1941
+
1593
1942
  /*
1594
1943
  * call-seq:
1595
1944
  * container.stop
@@ -1604,13 +1953,20 @@ container_stop(VALUE self)
1604
1953
 
1605
1954
  Data_Get_Struct(self, struct container_data, data);
1606
1955
 
1607
- ret = data->container->stop(data->container);
1956
+ ret = RELEASING_GVL(stop_without_gvl, data);
1608
1957
  if (!ret)
1609
1958
  rb_raise(Error, "unable to stop container");
1610
1959
 
1611
1960
  return self;
1612
1961
  }
1613
1962
 
1963
+ static RETURN_WITHOUT_GVL_TYPE
1964
+ unfreeze_without_gvl(void *data_void)
1965
+ {
1966
+ struct container_data *data = (struct container_data *)data_void;
1967
+ RETURN_WITHOUT_GVL(data->container->unfreeze(data->container));
1968
+ }
1969
+
1614
1970
  /*
1615
1971
  * call-seq:
1616
1972
  * container.unfreeze
@@ -1625,13 +1981,30 @@ container_unfreeze(VALUE self)
1625
1981
 
1626
1982
  Data_Get_Struct(self, struct container_data, data);
1627
1983
 
1628
- ret = data->container->unfreeze(data->container);
1984
+ ret = RELEASING_GVL(unfreeze_without_gvl, data);
1629
1985
  if (!ret)
1630
- rb_raise(Error, "unable to unfreeze container");
1986
+ rb_raise(Error, "unable to unfreeze container: %s", lxc_strerror(ret));
1631
1987
 
1632
1988
  return self;
1633
1989
  }
1634
1990
 
1991
+ struct wait_without_gvl_args {
1992
+ struct container_data *data;
1993
+ int timeout;
1994
+ char *state;
1995
+ };
1996
+
1997
+ static RETURN_WITHOUT_GVL_TYPE
1998
+ wait_without_gvl(void *args_void)
1999
+ {
2000
+ struct wait_without_gvl_args *args =
2001
+ (struct wait_without_gvl_args *)args_void;
2002
+ RETURN_WITHOUT_GVL(
2003
+ args->data->container->wait(args->data->container, args->state,
2004
+ args->timeout)
2005
+ );
2006
+ }
2007
+
1635
2008
  /*
1636
2009
  * call-seq:
1637
2010
  * container.wait(state, timeout = -1)
@@ -1642,22 +2015,21 @@ container_unfreeze(VALUE self)
1642
2015
  static VALUE
1643
2016
  container_wait(int argc, VALUE *argv, VALUE self)
1644
2017
  {
1645
- int ret, timeout;
1646
- char *state;
1647
- struct container_data *data;
2018
+ int ret;
1648
2019
  VALUE rb_state_str, rb_state, rb_timeout;
2020
+ struct wait_without_gvl_args args;
1649
2021
 
1650
2022
  rb_scan_args(argc, argv, "11", &rb_state, &rb_timeout);
1651
2023
 
1652
2024
  rb_state_str = rb_funcall(rb_state, rb_intern("to_s"), 0);
1653
2025
  rb_state_str = rb_funcall(rb_state_str, rb_intern("upcase"), 0);
1654
- state = StringValuePtr(rb_state_str);
2026
+ args.state = StringValuePtr(rb_state_str);
1655
2027
 
1656
- timeout = NIL_P(rb_timeout) ? -1 : NUM2INT(rb_timeout);
2028
+ args.timeout = NIL_P(rb_timeout) ? -1 : NUM2INT(rb_timeout);
1657
2029
 
1658
- Data_Get_Struct(self, struct container_data, data);
2030
+ Data_Get_Struct(self, struct container_data, args.data);
1659
2031
 
1660
- ret = data->container->wait(data->container, state, timeout);
2032
+ ret = RELEASING_GVL(wait_without_gvl, &args);
1661
2033
  if (!ret)
1662
2034
  rb_raise(Error, "error waiting for container");
1663
2035
 
@@ -1713,7 +2085,7 @@ Init_lxc(void)
1713
2085
  rb_define_method(Container, "load_config", container_load_config, -1);
1714
2086
  rb_define_method(Container, "reboot", container_reboot, 0);
1715
2087
  rb_define_method(Container, "remove_device_node",
1716
- container_remove_device_node, 0);
2088
+ container_remove_device_node, -1);
1717
2089
  rb_define_method(Container, "rename", container_rename, 1);
1718
2090
  rb_define_method(Container, "running_config_item",
1719
2091
  container_running_config_item, 1);
data/lib/lxc/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module LXC
2
- VERSION = '1.0.1'
2
+ VERSION = '1.0.2'
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-lxc
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-03-06 00:00:00.000000000 Z
12
+ date: 2014-03-29 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake-compiler