SystemTimer 1.0 → 1.1

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/ChangeLog CHANGED
@@ -1,3 +1,16 @@
1
+ === 1.1.0 / 2008-11-05
2
+
3
+ * New implementation supporting concurrent timers, i.e. :
4
+
5
+ (1..10).each do
6
+ Thread.new do
7
+ SystemTimer.timeout_after(5) do
8
+ sleep 60
9
+ puts "hi there!"
10
+ end
11
+ end
12
+ end
13
+
1
14
  === 1.0.0 / 2008-02-27
2
15
 
3
16
  * Initial Release
data/README CHANGED
@@ -5,6 +5,11 @@ solution to Ruby processes which hang beyond the time limit when accessing
5
5
  external resources. This is useful when timeout.rb, which relies on green
6
6
  threads, does not work consistently.
7
7
 
8
+ More background on:
9
+
10
+ * http://ph7spot.com/articles/system_timer
11
+ * http://davidvollbracht.com/2008/6/2/30-days-of-teach-day-1-systemtimer
12
+
8
13
  == Usage
9
14
 
10
15
  require 'systemtimer'
@@ -58,6 +63,8 @@ in particular MySQL.
58
63
  This implementation is not intended to be drop-in replacement to
59
64
  timeout.rb, just a way to wrap sensitive call to system resources.
60
65
 
66
+ You can find more details on SystemTimer and how to use it
67
+ at http://ph7spot.com/articles/system_timer
61
68
 
62
69
  == License
63
70
 
File without changes
@@ -1,7 +1,14 @@
1
+ /*
2
+ * SystemTimer native implementation relying on ITIMER_REAL
3
+ *
4
+ * Copyright 2008 David Vollbracht & Philippe Hanrigou
5
+ */
6
+
1
7
  #include "ruby.h"
2
8
  #include "rubysig.h"
3
9
  #include <signal.h>
4
10
  #include <errno.h>
11
+ #include <stdarg.h>
5
12
 
6
13
  #define DISPLAY_ERRNO 1
7
14
  #define DO_NOT_DISPLAY_ERRNO 0
@@ -11,103 +18,151 @@ sigset_t original_mask;
11
18
  sigset_t sigalarm_mask;
12
19
  struct sigaction original_signal_handler;
13
20
  struct itimerval original_timer_interval;
21
+ static int debug_enabled = 0;
14
22
 
15
23
  static void clear_pending_sigalrm_for_ruby_threads();
16
- static void log_debug(char*);
17
- static void log_error(char*, int);
18
24
  static void install_ruby_sigalrm_handler(VALUE);
19
25
  static void restore_original_ruby_sigalrm_handler(VALUE);
20
26
  static void restore_original_sigalrm_mask_when_blocked();
21
27
  static void restore_original_timer_interval();
28
+ static void set_itimerval_with_minimum_1s_interval(struct itimerval *, int);
22
29
  static void set_itimerval(struct itimerval *, int);
30
+ static void restore_sigalrm_mask(sigset_t *previous_mask);
31
+ static void log_debug(char*, ...);
32
+ static void log_error(char*, int);
23
33
 
24
- static int debug_enabled = 0;
25
34
 
26
- static VALUE install_timer(VALUE self, VALUE seconds)
35
+ static VALUE install_first_timer_and_save_original_configuration(VALUE self, VALUE seconds)
27
36
  {
28
- struct itimerval timer_interval;
29
-
30
- /*
31
- * Block SIG_ALRM for safe processing of SIG_ALRM configuration and save mask.
32
- */
33
- if (0 != sigprocmask(SIG_BLOCK, &sigalarm_mask, &original_mask)) {
34
- log_error("install_timer: Could not block SIG_ALRM", DISPLAY_ERRNO);
35
- return Qnil;
36
- }
37
- clear_pending_sigalrm_for_ruby_threads();
38
- log_debug("install_timer: Succesfully blocked SIG_ALRM at O.S. level");
37
+ struct itimerval timer_interval;
38
+
39
+ if (debug_enabled) {
40
+ log_debug("[install_first_timer] %d s\n", NUM2INT(seconds));
41
+ }
42
+
43
+ /*
44
+ * Block SIG_ALRM for safe processing of SIG_ALRM configuration and save mask.
45
+ */
46
+ if (0 != sigprocmask(SIG_BLOCK, &sigalarm_mask, &original_mask)) {
47
+ log_error("[install_first_timer] Could not block SIG_ALRM\n", DISPLAY_ERRNO);
48
+ return Qnil;
49
+ }
50
+ clear_pending_sigalrm_for_ruby_threads();
51
+ log_debug("[install_first_timer] Successfully blocked SIG_ALRM at O.S. level\n");
39
52
 
40
- /*
41
- * Save previous signal handler.
42
- */
43
- original_signal_handler.sa_handler = NULL;
44
- if (0 != sigaction(SIGALRM, NULL, &original_signal_handler)) {
45
- log_error("install_timer: Could not save existing handler for SIG_ALRM", DISPLAY_ERRNO);
46
- restore_original_sigalrm_mask_when_blocked();
47
- return Qnil;
48
- }
49
- log_debug("install_timer: Succesfully saved existing SIG_ALRM handler");
50
-
51
- /*
52
- * Install Ruby Level SIG_ALRM handler
53
- */
54
- install_ruby_sigalrm_handler(self);
55
-
56
- /*
57
- * Set new real time interval timer and save the original if any.
58
- */
59
- set_itimerval(&original_timer_interval, 0);
60
- set_itimerval(&timer_interval, NUM2INT(seconds));
61
- if (0 != setitimer(ITIMER_REAL, &timer_interval, &original_timer_interval)) {
62
- log_error("install_timer: Could not install our own timer, timeout will not work", DISPLAY_ERRNO);
63
- restore_original_ruby_sigalrm_handler(self);
64
- restore_original_sigalrm_mask_when_blocked();
65
- return Qnil;
66
- }
67
- log_debug("install_timer: Successfully installed timer");
68
-
69
- /*
70
- * Unblock SIG_ALRM
71
- */
72
- if (0 != sigprocmask(SIG_UNBLOCK, &sigalarm_mask, NULL)) {
73
- log_error("install_timer: Could not unblock SIG_ALRM, timeout will not work", DISPLAY_ERRNO);
74
- restore_original_timer_interval();
75
- restore_original_ruby_sigalrm_handler(self);
76
- restore_original_sigalrm_mask_when_blocked();
77
- }
78
- log_debug("install_timer: Succesfully unblocked SIG_ALRM.");
79
-
80
- return Qnil;
81
- }
82
-
83
- static VALUE cleanup_timer(VALUE self, VALUE seconds)
53
+ /*
54
+ * Save previous signal handler.
55
+ */
56
+ log_debug("[install_first_timer] Saving original system handler\n");
57
+ original_signal_handler.sa_handler = NULL;
58
+ if (0 != sigaction(SIGALRM, NULL, &original_signal_handler)) {
59
+ log_error("[install_first_timer] Could not save existing handler for SIG_ALRM\n", DISPLAY_ERRNO);
60
+ restore_original_sigalrm_mask_when_blocked();
61
+ return Qnil;
62
+ }
63
+ log_debug("[install_first_timer] Successfully saved existing SIG_ALRM handler\n");
64
+
65
+ /*
66
+ * Install Ruby Level SIG_ALRM handler
67
+ */
68
+ install_ruby_sigalrm_handler(self);
69
+
70
+ /*
71
+ * Save original real time interval timer and aet new real time interval timer.
72
+ */
73
+ set_itimerval(&original_timer_interval, 0);
74
+ set_itimerval_with_minimum_1s_interval(&timer_interval, seconds);
75
+ if (0 != setitimer(ITIMER_REAL, &timer_interval, &original_timer_interval)) {
76
+ log_error("[install_first_timer] Could not install our own timer, timeout will not work", DISPLAY_ERRNO);
77
+ restore_original_ruby_sigalrm_handler(self);
78
+ restore_original_sigalrm_mask_when_blocked();
79
+ return Qnil;
80
+ }
81
+ log_debug("[install_first_timer] Successfully installed timer (%ds)\n", timer_interval.it_value.tv_sec);
82
+
83
+ /*
84
+ * Unblock SIG_ALRM
85
+ */
86
+ if (0 != sigprocmask(SIG_UNBLOCK, &sigalarm_mask, NULL)) {
87
+ log_error("[install_first_timer] Could not unblock SIG_ALRM, timeout will not work", DISPLAY_ERRNO);
88
+ restore_original_timer_interval();
89
+ restore_original_ruby_sigalrm_handler(self);
90
+ restore_original_sigalrm_mask_when_blocked();
91
+ }
92
+ log_debug("[install_first_timer] Successfully unblocked SIG_ALRM.\n");
93
+
94
+ return Qnil;
95
+ }
96
+
97
+ static VALUE install_next_timer(VALUE self, VALUE seconds)
84
98
  {
85
- /*
86
- * Block SIG_ALRM for safe processing of SIG_ALRM configuration.
87
- */
88
- if (0 != sigprocmask(SIG_BLOCK, &sigalarm_mask, NULL)) {
89
- log_error("cleanup_timer: Could not block SIG_ALRM", errno);
90
- }
91
- clear_pending_sigalrm_for_ruby_threads();
92
- log_debug("cleanup_timer: Blocked SIG_ALRM");
93
-
94
- /*
95
- * Install Ruby Level SIG_ALRM handler
96
- */
97
- restore_original_ruby_sigalrm_handler(self);
99
+ struct itimerval timer_interval;
100
+ sigset_t previous_sigalarm_mask;
101
+
102
+ if (debug_enabled) {
103
+ log_debug("[install_next_timer] %ds\n", NUM2INT(seconds));
104
+ }
105
+
106
+ /*
107
+ * Block SIG_ALRM for safe processing of SIG_ALRM configuration and save mask.
108
+ */
109
+ if (0 != sigprocmask(SIG_BLOCK, &sigalarm_mask, &previous_sigalarm_mask)) {
110
+ log_error("[install_next_timer] Could not block SIG_ALRM\n", DISPLAY_ERRNO);
111
+ return Qnil;
112
+ }
113
+ clear_pending_sigalrm_for_ruby_threads();
114
+ log_debug("[install_next_timer] Successfully blocked SIG_ALRM at O.S. level\n");
98
115
 
116
+ /*
117
+ * Set new real time interval timer.
118
+ */
119
+ set_itimerval_with_minimum_1s_interval(&timer_interval, seconds);
120
+ if (0 != setitimer(ITIMER_REAL, &timer_interval, NULL)) {
121
+ log_error("[install_next_timer] Could not install our own timer, timeout will not work", DISPLAY_ERRNO);
122
+ restore_sigalrm_mask(&previous_sigalarm_mask);
123
+ return Qnil;
124
+ }
125
+ log_debug("[install_next_timer] Successfully installed timer (%ds)\n", timer_interval.it_value.tv_sec);
126
+
127
+ /*
128
+ * Unblock SIG_ALRM
129
+ */
130
+ if (0 != sigprocmask(SIG_UNBLOCK, &sigalarm_mask, NULL)) {
131
+ log_error("[install_next_timer] Could not unblock SIG_ALRM, timeout will not work", DISPLAY_ERRNO);
132
+ restore_sigalrm_mask(&previous_sigalarm_mask);
133
+ }
134
+ log_debug("[install_next_timer] Successfully unblocked SIG_ALRM.\n");
135
+
136
+ return Qnil;
137
+ }
138
+
139
+ static VALUE restore_original_configuration(VALUE self)
140
+ {
141
+ /*
142
+ * Block SIG_ALRM for safe processing of SIG_ALRM configuration.
143
+ */
144
+ if (0 != sigprocmask(SIG_BLOCK, &sigalarm_mask, NULL)) {
145
+ log_error("restore_original_configuration: Could not block SIG_ALRM", errno);
146
+ }
147
+ clear_pending_sigalrm_for_ruby_threads();
148
+ log_debug("[restore_original_configuration] Blocked SIG_ALRM\n");
149
+
150
+ /*
151
+ * Install Ruby Level SIG_ALRM handler
152
+ */
153
+ restore_original_ruby_sigalrm_handler(self);
99
154
 
100
- if (original_signal_handler.sa_handler == NULL) {
101
- log_error("cleanup_timer: Previous SIG_ALRM handler not initialized!", DO_NOT_DISPLAY_ERRNO);
102
- } else if (0 == sigaction(SIGALRM, &original_signal_handler, NULL)) {
103
- log_debug("cleanup_timer: Succesfully restored previous handler for SIG_ALRM");
104
- } else {
105
- log_error("cleanup_timer: Could not restore previous handler for SIG_ALRM", DISPLAY_ERRNO);
106
- }
107
- original_signal_handler.sa_handler = NULL;
155
+ if (original_signal_handler.sa_handler == NULL) {
156
+ log_error("[restore_original_configuration] Previous SIG_ALRM handler not initialized!", DO_NOT_DISPLAY_ERRNO);
157
+ } else if (0 == sigaction(SIGALRM, &original_signal_handler, NULL)) {
158
+ log_debug("[restore_original_configuration] Successfully restored previous handler for SIG_ALRM\n");
159
+ } else {
160
+ log_error("[restore_original_configuration] Could not restore previous handler for SIG_ALRM", DISPLAY_ERRNO);
161
+ }
162
+ original_signal_handler.sa_handler = NULL;
108
163
 
109
- restore_original_timer_interval();
110
- restore_original_sigalrm_mask_when_blocked();
164
+ restore_original_timer_interval();
165
+ restore_original_sigalrm_mask_when_blocked();
111
166
  }
112
167
 
113
168
  /*
@@ -119,61 +174,70 @@ static VALUE cleanup_timer(VALUE self, VALUE seconds)
119
174
  *
120
175
  */
121
176
  static void restore_original_timer_interval() {
122
- if (0 != setitimer (ITIMER_REAL, &original_timer_interval, NULL)) {
123
- log_error("install_timer: Could not restore original timer", DISPLAY_ERRNO);
124
- }
125
- log_debug("install_timer: Successfully restored timer");
177
+ if (0 != setitimer(ITIMER_REAL, &original_timer_interval, NULL)) {
178
+ log_error("[restore_original_configuration] Could not restore original timer", DISPLAY_ERRNO);
179
+ }
180
+ log_debug("[restore_original_configuration] Successfully restored original timer\n");
181
+ }
182
+
183
+ static void restore_sigalrm_mask(sigset_t *previous_mask)
184
+ {
185
+ if (!sigismember(previous_mask, SIGALRM)) {
186
+ sigprocmask(SIG_UNBLOCK, &sigalarm_mask, NULL);
187
+ log_debug("[restore_sigalrm_mask] Unblocked SIG_ALRM\n");
188
+ } else {
189
+ log_debug("[restore_sigalrm_mask] No Need to unblock SIG_ALRM\n");
190
+ }
126
191
  }
127
192
 
128
193
  static void restore_original_sigalrm_mask_when_blocked()
129
194
  {
130
- if (!sigismember(&original_mask, SIGALRM)) {
131
- sigprocmask(SIG_UNBLOCK, &sigalarm_mask, NULL);
132
- log_debug("cleanup_timer: Unblocked SIG_ALRM");
133
- } else {
134
- log_debug("cleanup_timer: No Need to unblock SIG_ALRM");
135
- }
195
+ restore_sigalrm_mask(&original_mask);
136
196
  }
137
197
 
138
198
  static void install_ruby_sigalrm_handler(VALUE self) {
139
- rb_thread_critical = 1;
140
- rb_funcall(self, rb_intern("install_ruby_sigalrm_handler"), 0);
141
- rb_thread_critical = 0;
199
+ rb_thread_critical = 1;
200
+ rb_funcall(self, rb_intern("install_ruby_sigalrm_handler"), 0);
201
+ rb_thread_critical = 0;
142
202
  }
143
203
 
144
204
  static void restore_original_ruby_sigalrm_handler(VALUE self) {
145
- rb_thread_critical = 1;
146
- rb_funcall(self, rb_intern("restore_original_ruby_sigalrm_handler"), 0);
147
- rb_thread_critical = 0;
205
+ rb_thread_critical = 1;
206
+ rb_funcall(self, rb_intern("restore_original_ruby_sigalrm_handler"), 0);
207
+ rb_thread_critical = 0;
148
208
  }
149
209
 
150
210
 
151
211
  static VALUE debug_enabled_p(VALUE self) {
152
- return debug_enabled ? Qtrue : Qfalse;
212
+ return debug_enabled ? Qtrue : Qfalse;
153
213
  }
154
214
 
155
215
  static VALUE enable_debug(VALUE self) {
156
- debug_enabled = 1;
157
- return Qnil;
216
+ debug_enabled = 1;
217
+ return Qnil;
158
218
  }
159
219
 
160
220
  static VALUE disable_debug(VALUE self) {
161
- debug_enabled = 0;
162
- return Qnil;
221
+ debug_enabled = 0;
222
+ return Qnil;
163
223
  }
164
224
 
165
- static void log_debug(char* message)
225
+ static void log_debug(char* message, ...)
166
226
  {
167
- if (0 != debug_enabled) {
168
- printf("%s\n", message);
169
- }
170
- return;
227
+ va_list argp;
228
+
229
+ if (0 != debug_enabled) {
230
+ va_start(argp, message);
231
+ vfprintf(stdout, message, argp);
232
+ va_end(argp);
233
+ }
234
+ return;
171
235
  }
172
236
 
173
237
  static void log_error(char* message, int display_errno)
174
238
  {
175
- fprintf(stderr, "%s: %s\n", message, display_errno ? strerror(errno) : "");
176
- return;
239
+ fprintf(stderr, "%s: %s\n", message, display_errno ? strerror(errno) : "");
240
+ return;
177
241
  }
178
242
 
179
243
  /*
@@ -186,32 +250,45 @@ static void log_error(char* message, int display_errno)
186
250
  */
187
251
  static void clear_pending_sigalrm_for_ruby_threads()
188
252
  {
189
- CHECK_INTS;
190
- log_debug("Succesfully triggered all pending signals at Green Thread level");
253
+ CHECK_INTS;
254
+ log_debug("[native] Successfully triggered all pending signals at Green Thread level\n");
191
255
  }
192
256
 
193
257
  static void init_sigalarm_mask()
194
258
  {
195
- sigemptyset(&sigalarm_mask);
196
- sigaddset(&sigalarm_mask, SIGALRM);
197
- return;
259
+ sigemptyset(&sigalarm_mask);
260
+ sigaddset(&sigalarm_mask, SIGALRM);
261
+ return;
262
+ }
263
+
264
+ static void set_itimerval_with_minimum_1s_interval(struct itimerval *value,
265
+ int seconds) {
266
+
267
+ int sanitized_second_interval;
268
+
269
+ sanitized_second_interval = NUM2INT(seconds);
270
+ if (sanitized_second_interval <= 0 ) {
271
+ sanitized_second_interval = 1;
272
+ }
273
+ set_itimerval(value, sanitized_second_interval);
198
274
  }
199
275
 
200
276
  static void set_itimerval(struct itimerval *value, int seconds) {
201
- value->it_interval.tv_usec = 0;
202
- value->it_interval.tv_sec = 0;
203
- value->it_value.tv_usec = 0;
204
- value->it_value.tv_sec = seconds; // (long int)
205
- return;
277
+ value->it_interval.tv_usec = 0;
278
+ value->it_interval.tv_sec = 0;
279
+ value->it_value.tv_usec = 0;
280
+ value->it_value.tv_sec = seconds; // (long int)
281
+ return;
206
282
  }
207
283
 
208
284
  void Init_system_timer_native()
209
285
  {
210
- init_sigalarm_mask();
211
- rb_cSystemTimer = rb_define_module("SystemTimer");
212
- rb_define_singleton_method(rb_cSystemTimer, "install_timer", install_timer, 1);
213
- rb_define_singleton_method(rb_cSystemTimer, "cleanup_timer", cleanup_timer, 0);
214
- rb_define_singleton_method(rb_cSystemTimer, "debug_enabled?", debug_enabled_p, 0);
215
- rb_define_singleton_method(rb_cSystemTimer, "enable_debug", enable_debug, 0);
216
- rb_define_singleton_method(rb_cSystemTimer, "disable_debug", disable_debug, 0);
286
+ init_sigalarm_mask();
287
+ rb_cSystemTimer = rb_define_module("SystemTimer");
288
+ rb_define_singleton_method(rb_cSystemTimer, "install_first_timer_and_save_original_configuration", install_first_timer_and_save_original_configuration, 1);
289
+ rb_define_singleton_method(rb_cSystemTimer, "install_next_timer", install_next_timer, 1);
290
+ rb_define_singleton_method(rb_cSystemTimer, "restore_original_configuration", restore_original_configuration, 0);
291
+ rb_define_singleton_method(rb_cSystemTimer, "debug_enabled?", debug_enabled_p, 0);
292
+ rb_define_singleton_method(rb_cSystemTimer, "enable_debug", enable_debug, 0);
293
+ rb_define_singleton_method(rb_cSystemTimer, "disable_debug", disable_debug, 0);
217
294
  }
@@ -1,11 +1,21 @@
1
+ # Copyright 2008 David Vollbracht & Philippe Hanrigou
2
+
1
3
  require 'rubygems'
2
4
  require 'timeout'
5
+ require 'forwardable'
6
+ require File.dirname(__FILE__) + '/system_timer/thread_timer'
7
+ require File.dirname(__FILE__) + '/system_timer/concurrent_timer_pool'
3
8
 
4
- # Timer based on underlying SIGALRM system timers, is a
9
+ # Timer based on underlying +ITIMER_REAL+ system timer. It is a
5
10
  # solution to Ruby processes which hang beyond the time limit when accessing
6
11
  # external resources. This is useful when timeout.rb, which relies on green
7
12
  # threads, does not work consistently.
8
13
  #
14
+ # For more information and background check out:
15
+ #
16
+ # * http://ph7spot.com/articles/system_timer
17
+ # * http://davidvollbracht.com/2008/6/2/30-days-of-teach-day-1-systemtimer
18
+ #
9
19
  # == Usage
10
20
  #
11
21
  # require 'systemtimer'
@@ -17,54 +27,79 @@ require 'timeout'
17
27
  #
18
28
  # end
19
29
  #
20
- module SystemTimer
21
- class << self
22
-
23
- # Executes the method's block. If the block execution terminates before
24
- # +seconds+ seconds has passed, it returns true. If not, it terminates
25
- # the execution and raises a +Timeout::Error+.
26
- def timeout_after(seconds)
27
- install_timer(seconds)
28
- return yield
29
- ensure
30
- cleanup_timer
31
- end
30
+ module SystemTimer
32
31
 
33
- # Backward compatibility with timeout.rb
34
- alias timeout timeout_after
32
+ Thread.exclusive do # Avoid race conditions for mutex and pool creation
33
+ @timer_pool = ConcurrentTimerPool.new
34
+ @mutex = Mutex.new
35
+ end
36
+
37
+ class << self
38
+ attr_reader :timer_pool
39
+
40
+ # Executes the method's block. If the block execution terminates before
41
+ # +seconds+ seconds has passed, it returns true. If not, it terminates
42
+ # the execution and raises a +Timeout::Error+.
43
+ def timeout_after(seconds)
44
+ new_timer = nil # just for scope
45
+ @mutex.synchronize do
46
+ new_timer = timer_pool.add_timer seconds
47
+ timer_interval = timer_pool.next_trigger_interval_in_seconds
48
+ debug "==== Install Timer ==== at #{Time.now.to_i}, next interval: #{timer_interval}"
49
+ if timer_pool.first_timer?
50
+ install_first_timer_and_save_original_configuration timer_interval
51
+ else
52
+ install_next_timer timer_interval
53
+ end
54
+ end
55
+ return yield
56
+ ensure
57
+ @mutex.synchronize do
58
+ debug "==== Cleanup Timer ==== at #{Time.now.to_i}, #{new_timer} "
59
+ timer_pool.cancel new_timer
60
+ timer_pool.log_registered_timers if debug_enabled?
61
+ next_interval = timer_pool.next_trigger_interval_in_seconds
62
+ debug "Cleanup Timer : next interval #{next_interval.inspect} "
63
+ if next_interval
64
+ install_next_timer next_interval
65
+ else
66
+ restore_original_configuration
67
+ end
68
+ end
69
+ end
70
+
71
+ # Backward compatibility with timeout.rb
72
+ alias timeout timeout_after
35
73
 
36
74
  protected
37
75
 
38
- def install_ruby_sigalrm_handler #:nodoc:
39
- timed_thread = Thread.current # Ruby signals are always delivered to main thread by default.
76
+ def install_ruby_sigalrm_handler #:nodoc:
40
77
  @original_ruby_sigalrm_handler = trap('SIGALRM') do
41
- log_timeout_received(timed_thread) if SystemTimer.debug_enabled?
42
- timed_thread.raise Timeout::Error.new("time's up!")
43
- end
78
+ @mutex.synchronize do
79
+ # Triggers timers one at a time to ensure more deterministic results
80
+ timer_pool.trigger_next_expired_timer
81
+ end
82
+ end
44
83
  end
45
84
 
46
- def restore_original_ruby_sigalrm_handler #:nodoc:
85
+ def restore_original_ruby_sigalrm_handler #:nodoc:
47
86
  trap('SIGALRM', original_ruby_sigalrm_handler || 'DEFAULT')
48
87
  ensure
49
88
  reset_original_ruby_sigalrm_handler
50
89
  end
51
90
 
52
- def original_ruby_sigalrm_handler #:nodoc:
91
+ def original_ruby_sigalrm_handler #:nodoc:
53
92
  @original_ruby_sigalrm_handler
54
93
  end
55
94
 
56
- def reset_original_ruby_sigalrm_handler #:nodoc:
95
+ def reset_original_ruby_sigalrm_handler #:nodoc:
57
96
  @original_ruby_sigalrm_handler = nil
58
97
  end
59
98
 
60
- def log_timeout_received(timed_thread) #:nodoc:
61
- puts <<-EOS
62
- install_ruby_sigalrm_handler: Got Timeout in #{Thread.current}
63
- Main thread : #{Thread.main}
64
- Timed_thread : #{timed_thread}
65
- All Threads : #{Thread.list.inspect}
66
- EOS
99
+ def debug(message) #:nodoc
100
+ puts message if debug_enabled?
67
101
  end
102
+
68
103
  end
69
104
 
70
105
  end