serverengine 1.5.3 → 1.5.4

Sign up to get free protection for your applications and to get access to all the features.
data/Changelog CHANGED
@@ -1,4 +1,10 @@
1
1
 
2
+ 2013-09-10 version 1.5.4:
3
+
4
+ * SignalThread: fixed "Unexpected error can't be called from trap context"
5
+ error in Ruby 2.0 (Thanks to @jondot and @sonots)
6
+
7
+
2
8
  2013-06-30 version 1.5.3:
3
9
 
4
10
  * Daemon: uses Process::UID.from_name and Process::GID.from_name
@@ -88,8 +88,8 @@ module ServerEngine
88
88
  def run
89
89
  begin
90
90
  exit main
91
- rescue
92
- ServerEngine.dump_uncaught_error($!)
91
+ rescue => e
92
+ ServerEngine.dump_uncaught_error(e)
93
93
  exit @daemonize_error_exit_code
94
94
  end
95
95
  end
@@ -43,7 +43,7 @@ module ServerEngine
43
43
 
44
44
  old = @handlers[sig]
45
45
  if block
46
- Kernel.trap(sig) { enqueue(sig) }
46
+ Kernel.trap(sig) { signal_handler_main(sig) }
47
47
  @handlers[sig] = block
48
48
  else
49
49
  Kernel.trap(sig, command)
@@ -59,83 +59,58 @@ module ServerEngine
59
59
 
60
60
  def stop
61
61
  @mutex.synchronize do
62
- ## synchronized state 1
63
62
  @finished = true
64
63
  @cond.broadcast
65
- ## synchronized state 2
66
64
  end
67
65
  self
68
66
  end
69
67
 
70
68
  private
71
69
 
72
- def main
73
- @mutex.lock
70
+ def signal_handler_main(sig)
71
+ # here always creates new thread to avoid
72
+ # complicated race conditin in signal handlers
73
+ Thread.new do
74
+ begin
75
+ enqueue(sig)
76
+ rescue => e
77
+ ServerEngine.dump_uncaught_error(e)
78
+ end
79
+ end
80
+ end
74
81
 
82
+ def main
75
83
  until @finished
76
- ## synchronized state 3
84
+ sig = nil
77
85
 
78
- sig = @queue.shift
79
- unless sig
80
- ## synchronized state 4
81
- @cond.wait(@mutex, 1)
82
- next
83
- end
86
+ @mutex.synchronize do
87
+ while true
88
+ return if @finished
84
89
 
85
- ## synchronized state 5
90
+ sig = @queue.shift
91
+ break if sig
92
+
93
+ @cond.wait(@mutex, 1)
94
+ end
95
+ end
86
96
 
87
- @mutex.unlock
88
97
  begin
89
98
  @handlers[sig].call(sig)
90
- rescue
91
- ServerEngine.dump_uncaught_error($!)
92
- ensure
93
- @mutex.lock
99
+ rescue => e
100
+ ServerEngine.dump_uncaught_error(e)
94
101
  end
95
102
  end
96
103
 
97
- ## synchronized state 6
98
104
  nil
99
105
 
100
106
  ensure
101
- @mutex.unlock
102
107
  @finished = false
103
108
  end
104
109
 
105
110
  def enqueue(sig)
106
- @queue << sig
107
-
108
- unless @mutex.try_lock
109
- #
110
- # here couldn't acquire @mutex.
111
- #
112
- # A) a thread is in synchronized state 1 or 2.
113
- # In this case, here doesn't have to broadcast because the thread will/did broadcast.
114
- #
115
- # B) `self` thread is in synchronized state 3
116
- # In this case, here doesn't have to broadcast because the `self` thread will
117
- # take a task from the queue soon.
118
- #
119
- # C) `self` thread is in synchronized state 4
120
- # In this case, here needs to broadcast but doesn't broadcast. Thus it causes
121
- # blocking upto 1 second :(
122
- #
123
- # D) `self` thread is in synchronized state 5
124
- # In this case, here doesn't have to broadcast because the `self` thread will
125
- # change to synchronized state 3 or 6 soon.
126
- #
127
- # E) the main thread (the only thread which calls this method) is in synchronized
128
- # state 7. In this case, here doesn't have to broadcast.
129
- #
130
- return
131
- end
132
-
133
- ## synchronized state 7
134
-
135
- begin
111
+ @mutex.synchronize do
112
+ @queue << sig
136
113
  @cond.broadcast
137
- ensure
138
- @mutex.unlock
139
114
  end
140
115
  end
141
116
 
@@ -1,3 +1,3 @@
1
1
  module ServerEngine
2
- VERSION = "1.5.3"
2
+ VERSION = "1.5.4"
3
3
  end
@@ -44,6 +44,7 @@ describe ServerEngine::BlockingFlag do
44
44
  started = BlockingFlag.new
45
45
  t = Thread.new do
46
46
  started.set!
47
+ Thread.pass
47
48
  subject.wait_for_set(1)
48
49
  elapsed = Time.now - start
49
50
  end
@@ -1,32 +1,39 @@
1
1
 
2
- require 'pstore'
2
+ require 'thread'
3
+ require 'yaml'
3
4
 
4
5
  def reset_test_state
5
6
  FileUtils.mkdir_p 'tmp'
6
- FileUtils.rm_f 'tmp/state.pstore'
7
- FileUtils.touch 'tmp/state.pstore'
7
+ FileUtils.rm_f 'tmp/state.yml'
8
+ FileUtils.touch 'tmp/state.yml'
9
+ $state_file_mutex = Mutex.new
8
10
  end
9
11
 
10
12
  def incr_test_state(key)
11
- ps = PStore.new('tmp/state.pstore')
12
- ps.transaction do
13
- ps[key] ||= 0
14
- ps[key] += 1
13
+ File.open('tmp/state.yml', 'r+') do |f|
14
+ f.flock(File::LOCK_EX)
15
+
16
+ $state_file_mutex.synchronize do
17
+ data = YAML.load(f.read) || {} rescue {}
18
+ data[key] ||= 0
19
+ data[key] += 1
20
+
21
+ f.pos = 0
22
+ f.write YAML.dump(data)
23
+ end
15
24
  end
16
25
  end
17
26
 
18
27
  def test_state(key)
19
- ps = PStore.new('tmp/state.pstore')
20
- ps.transaction do
21
- return ps[key] || 0
22
- end
28
+ data = YAML.load_file('tmp/state.yml') || {} rescue {}
29
+ return data[key] || 0
23
30
  end
24
31
 
25
32
  shared_context 'test server and worker' do
26
33
  before { reset_test_state }
27
34
 
28
35
  def wait_for_fork
29
- sleep 0.2
36
+ sleep 0.8
30
37
  end
31
38
 
32
39
  def wait_for_stop
@@ -97,7 +104,11 @@ shared_context 'test server and worker' do
97
104
 
98
105
  def run
99
106
  incr_test_state :worker_run
100
- @stop_flag.wait(5.0)
107
+ 5.times do
108
+ # repeats 5 times because signal handlers
109
+ # interrupts wait
110
+ @stop_flag.wait(5.0)
111
+ end
101
112
  @stop_flag.reset!
102
113
  end
103
114
 
@@ -14,6 +14,7 @@ describe ServerEngine::SignalThread do
14
14
  end
15
15
 
16
16
  Process.kill('CONT', Process.pid)
17
+ sleep 0.5
17
18
 
18
19
  t.stop.join
19
20
 
@@ -43,8 +44,7 @@ describe ServerEngine::SignalThread do
43
44
  end
44
45
 
45
46
  Process.kill('QUIT', Process.pid)
46
-
47
- sleep 1
47
+ sleep 0.5
48
48
 
49
49
  n.should == 3
50
50
  end
@@ -57,6 +57,7 @@ describe ServerEngine::SignalThread do
57
57
  end
58
58
 
59
59
  Process.kill('QUIT', Process.pid)
60
+ sleep 0.5
60
61
 
61
62
  t.join
62
63
  end
@@ -53,6 +53,7 @@ describe ServerEngine::Supervisor do
53
53
  wait_for_fork
54
54
 
55
55
  sv.restart(true)
56
+ wait_for_stop
56
57
 
57
58
  ensure
58
59
  sv.stop(true)
@@ -74,6 +75,7 @@ describe ServerEngine::Supervisor do
74
75
  wait_for_fork
75
76
 
76
77
  sv.restart(false)
78
+ wait_for_stop
77
79
 
78
80
  ensure
79
81
  sv.stop(true)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: serverengine
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.3
4
+ version: 1.5.4
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: 2013-07-01 00:00:00.000000000 Z
12
+ date: 2013-09-10 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: sigdump