cztop-reactor 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f70c203f7ad3e56ab62f3a274d7e0bcd6bc0a845
4
- data.tar.gz: f7166b3b4c013035f61ea88e4839fdb8cec1517e
3
+ metadata.gz: 7040196abcd091e72df775bcb4c4dc6ebca8781c
4
+ data.tar.gz: 3da1c1b5f4ef14d63d2ef16d502c10de3cf8a0e7
5
5
  SHA512:
6
- metadata.gz: f24b280136af590d7c05685d7db0a31e702f2b013fb9bce3ed3271579ecf917d47faa81d3c0bcb289422b7ed819fc599ee75f5dc5dfc309188b14b2e2159cd16
7
- data.tar.gz: f1477bbfb5427e0e62e2309160231f515062e25fdc2ec440361817c0a69d070c9d07adb13e217b51368684f702d30f4b24169b7bcf6e90486a272e9b4a9ddc5f
6
+ metadata.gz: 2b7ccd0a2736e3cfc0af5408c1ee804ac1163c5f2ea730f9f21a3a6a5c17c71aa46784585d133cc510d3d85e07ad764b397f440bfb98c1f79c55abea6ec5dbf9
7
+ data.tar.gz: '0845fbba1711499f0bee3caf9c09a893c9e0d4395cdb24f943bcded4113d8dade8c9cdd153ff979a7b4b19fb8ef709d8eef42f03e3320b10deb1c6399196afab'
Binary file
data.tar.gz.sig CHANGED
Binary file
data/ChangeLog CHANGED
@@ -1,8 +1,39 @@
1
+ 2017-05-15 Michael Granger <ged@FaerieMUD.org>
2
+
3
+ * .hgignore, Manifest.txt, lib/cztop/reactor/signal_handling.rb,
4
+ spec/cztop/reactor/signal_handling_spec.rb:
5
+ Add a mixin for signal handling.
6
+ [970a2eb110fb] [tip]
7
+
8
+ 2017-04-30 Michael Granger <ged@FaerieMUD.org>
9
+
10
+ * .hgignore:
11
+ Ignore pkg directory
12
+ [1c8f915143cf]
13
+
14
+ 2017-04-29 Michael Granger <ged@FaerieMUD.org>
15
+
16
+ * .hgtags:
17
+ Added tag v0.2.0 for changeset 05892f4b1e67
18
+ [188620133448]
19
+
20
+ * .hgsigs:
21
+ Added signature for changeset 94faa8741253
22
+ [05892f4b1e67] [v0.2.0]
23
+
24
+ * History.md, lib/cztop/reactor.rb:
25
+ Bump the minor version, update history.
26
+ [94faa8741253]
27
+
28
+ * lib/cztop/reactor.rb, spec/cztop/reactor_spec.rb:
29
+ Allow timers to be resumed after they're removed.
30
+ [2318715be614]
31
+
1
32
  2017-04-19 Michael Granger <ged@FaerieMUD.org>
2
33
 
3
34
  * Rakefile, cztop-reactor.gemspec:
4
35
  Remove Rakefile guard against public release.
5
- [bb56a75ae424] [tip]
36
+ [bb56a75ae424]
6
37
 
7
38
  2017-04-12 Michael Granger <ged@FaerieMUD.org>
8
39
 
data/History.md CHANGED
@@ -1,3 +1,10 @@
1
+ ## v0.3.0 [2017-05-15] Michael Granger <ged@FaerieMUD.org>
2
+
3
+ Enhancements:
4
+
5
+ - Add a mixin for adding queued signal handling to the polling loop.
6
+
7
+
1
8
  ## v0.2.0 [2017-04-29] Michael Granger <ged@FaerieMUD.org>
2
9
 
3
10
  Enhancements:
@@ -9,6 +9,8 @@ README.md
9
9
  Rakefile
10
10
  lib/cztop/reactor.rb
11
11
  lib/cztop/reactor/event.rb
12
+ lib/cztop/reactor/signal_handling.rb
12
13
  spec/cztop/reactor/event_spec.rb
14
+ spec/cztop/reactor/signal_handling_spec.rb
13
15
  spec/cztop/reactor_spec.rb
14
16
  spec/spec_helper.rb
@@ -22,7 +22,7 @@ class CZTop::Reactor
22
22
  extend Loggability
23
23
 
24
24
  # The version of this library
25
- VERSION = '0.2.0'
25
+ VERSION = '0.3.0'
26
26
 
27
27
  # The maximum number of seconds to wait for events when there are no timers
28
28
  # registered.
@@ -0,0 +1,164 @@
1
+ # -*- ruby -*-
2
+ #encoding: utf-8
3
+
4
+ require 'loggability'
5
+ require 'securerandom'
6
+ require 'cztop/reactor' unless defined?( CZTop::Reactor )
7
+
8
+
9
+ # A mixin that adds methods for running a process with queued signal handling
10
+ # via a ZMQ PAIR socket.
11
+ #
12
+ # require 'cztop'
13
+ # require 'cztop/reactor'
14
+ # require 'cztop/reactor/signal_handling'
15
+ #
16
+ # class MyDaemon
17
+ # include 'cztop/reactor/signal_handling'
18
+ #
19
+ # def start
20
+ # @reactor = CZTop::Reactor.new
21
+ # @reactor.register( @socket, :read, &self.method(:handle_io_event) )
22
+ # self.with_signal_handler( @reactor, :HUP, :INT, :TERM ) do
23
+ # @reactor.start_polling( ignore_interrupts: true )
24
+ # end
25
+ # end
26
+ #
27
+ # def stop
28
+ # @reactor.stop_polling
29
+ # end
30
+ #
31
+ # def handle_signal( signal_name )
32
+ # case signal_name
33
+ # when :INT, :TERM, :HUP
34
+ # self.stop
35
+ # else
36
+ # super
37
+ # end
38
+ # end
39
+ # end
40
+ #
41
+ # With this mixin included, you can wrap a block with a call to
42
+ # #with_signal_handler, and when a signal arrives, the #handle_signal method
43
+ # will be called with the name of the signal.
44
+ module CZTop::Reactor::SignalHandling
45
+
46
+
47
+ # The name of the thread-local variable that stores pending signals.
48
+ SIGNAL_QUEUE_KEY = :signal_queue
49
+
50
+
51
+ ### Inclusion callback -- add Loggability to including classes.
52
+ def self::included( mod )
53
+ super
54
+ mod.extend( Loggability )
55
+ mod.log_to( :cztop ) unless Loggability.log_host?( mod )
56
+ end
57
+
58
+
59
+ ### Wrap a block in signal-handling.
60
+ def with_signal_handler( reactor, *signals )
61
+ self.set_up_signal_handling( reactor )
62
+ self.set_signal_traps( *signals )
63
+
64
+ return yield
65
+
66
+ ensure
67
+ self.reset_signal_traps( *signals )
68
+ self.clean_up_signal_handling( reactor )
69
+ end
70
+
71
+
72
+ ### Simulate the receipt of the specified +signal+ (probably only useful
73
+ ### in testing).
74
+ def simulate_signal( signal )
75
+ Thread.main[ SIGNAL_QUEUE_KEY ] << signal.to_sym
76
+ self.wake_up
77
+ end
78
+
79
+
80
+ #########
81
+ protected
82
+ #########
83
+
84
+ ### Set up data structures for signal handling.
85
+ def set_up_signal_handling( reactor )
86
+ Thread.main[ SIGNAL_QUEUE_KEY ] = []
87
+
88
+ endpoint = "inproc://signal-handler-%s" % [ SecureRandom.hex(8) ]
89
+ @self_pipe = {
90
+ reader: CZTop::Socket::PAIR.new( "@#{endpoint}" ),
91
+ writer: CZTop::Socket::PAIR.new( ">#{endpoint}" )
92
+ }
93
+
94
+ # :TODO: Consider calling #set_unbounded on the PAIR sockets
95
+
96
+ reactor.register( @self_pipe[:reader], :read, &self.method(:handle_queued_signals) )
97
+ end
98
+
99
+
100
+ ### Tear down the data structures for signal handling
101
+ def clean_up_signal_handling( reactor )
102
+ reactor.unregister( @self_pipe[:reader] )
103
+
104
+ @self_pipe[:writer].options.linger = 0
105
+ @self_pipe[:writer].close
106
+ @self_pipe[:reader].options.linger = 0
107
+ @self_pipe[:reader].close
108
+
109
+ Thread.main[ SIGNAL_QUEUE_KEY ].clear
110
+ end
111
+
112
+
113
+ ### Look for any signals that arrived and handle them.
114
+ def handle_queued_signals( _event )
115
+ while sig = Thread.main[ SIGNAL_QUEUE_KEY ].shift
116
+ self.log.debug " got a queued signal: %p" % [ sig ]
117
+ self.handle_signal( sig )
118
+ end
119
+ end
120
+
121
+
122
+ ### Default signal-handler callback -- this raises an exception by default.
123
+ def handle_signal( signal_name )
124
+ raise NotImplementedError, "unhandled signal %s" % [ signal_name ]
125
+ end
126
+
127
+
128
+ ### Signal through the self-pipe that one or more signals has been queued.
129
+ def wake_up
130
+ @self_pipe[:writer].signal( 1 )
131
+ end
132
+
133
+
134
+ ### Set up signal traps for the specified +signals+.
135
+ def set_signal_traps( *signals )
136
+ self.log.debug "Setting up deferred signal handlers."
137
+ signals.each do |sig|
138
+ Signal.trap( sig ) do
139
+ Thread.main[ SIGNAL_QUEUE_KEY ] << sig
140
+ self.wake_up
141
+ end
142
+ end
143
+ end
144
+
145
+
146
+ ### Set the traps for the specified +signals+ to IGNORE.
147
+ def ignore_signals( *signals )
148
+ self.log.debug "Ignoring signals."
149
+ signals.each do |sig|
150
+ next if sig == :CHLD
151
+ Signal.trap( sig, :IGNORE )
152
+ end
153
+ end
154
+
155
+
156
+ ### Set the traps for the specified +signals+ to the default handler.
157
+ def reset_signal_traps( *signals )
158
+ self.log.debug "Restoring default signal handlers."
159
+ signals.each do |sig|
160
+ Signal.trap( sig, :DEFAULT )
161
+ end
162
+ end
163
+
164
+ end # module CZTop::Reactor::SignalHandling
@@ -0,0 +1,57 @@
1
+ #!/usr/bin/env rspec -cfd
2
+
3
+ require_relative '../../spec_helper'
4
+
5
+ require 'cztop/reactor/signal_handling'
6
+
7
+
8
+ describe CZTop::Reactor::SignalHandling do
9
+
10
+ it "can add a signal handler setup to a reactor for a block" do
11
+ including_class = Class.new do
12
+
13
+ def initialize
14
+ @signals = []
15
+ end
16
+
17
+ attr_reader :signals
18
+
19
+ def handle_signal( signal_name )
20
+ self.signals << signal_name
21
+ end
22
+
23
+ end
24
+
25
+ including_class.include( described_class )
26
+
27
+ obj = including_class.new
28
+ reactor = CZTop::Reactor.new
29
+
30
+ obj.with_signal_handler( reactor, :USR1 ) do
31
+ obj.log.debug( "Killing with USR1" )
32
+ Process.kill( :USR1, Process.pid )
33
+ reactor.poll_once
34
+ end
35
+
36
+ expect( obj.signals ).to eq([ :USR1 ])
37
+ end
38
+
39
+
40
+ it "raises if the including class doesn't provide a #handle_signal method" do
41
+ including_class = Class.new
42
+ including_class.include( described_class )
43
+
44
+ obj = including_class.new
45
+ reactor = CZTop::Reactor.new
46
+
47
+ expect {
48
+ obj.with_signal_handler( reactor, :USR1 ) do
49
+ obj.log.debug( "Killing with USR1" )
50
+ Process.kill( :USR1, Process.pid )
51
+ reactor.poll_once
52
+ end
53
+ }.to raise_error( NotImplementedError, /unhandled signal USR1/i )
54
+ end
55
+
56
+ end
57
+
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cztop-reactor
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Granger
@@ -35,7 +35,7 @@ cert_chain:
35
35
  w8aNA5re5+Rt/Vvjxj5AcEnZnZiz5x959NaddQocX32Z1unHw44pzRNUur1GInfW
36
36
  p4vpx2kUSFSAGjtCbDGTNV2AH8w9OU4xEmNz8c5lyoA=
37
37
  -----END CERTIFICATE-----
38
- date: 2017-04-29 00:00:00.000000000 Z
38
+ date: 2017-05-16 00:00:00.000000000 Z
39
39
  dependencies:
40
40
  - !ruby/object:Gem::Dependency
41
41
  name: loggability
@@ -217,7 +217,9 @@ files:
217
217
  - Rakefile
218
218
  - lib/cztop/reactor.rb
219
219
  - lib/cztop/reactor/event.rb
220
+ - lib/cztop/reactor/signal_handling.rb
220
221
  - spec/cztop/reactor/event_spec.rb
222
+ - spec/cztop/reactor/signal_handling_spec.rb
221
223
  - spec/cztop/reactor_spec.rb
222
224
  - spec/spec_helper.rb
223
225
  homepage: http://deveiate.org/projects/cztop-reactor
metadata.gz.sig CHANGED
Binary file