ruby-lxc 1.0.1 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
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