serverengine 1.5.3 → 1.5.4

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,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