tlconnor-spawn 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ *~
2
+ *.gem
data/CHANGELOG ADDED
@@ -0,0 +1,55 @@
1
+ v0.1 - 2007/09/13
2
+
3
+ initial version
4
+
5
+ --------------------------------------------------
6
+ v0.2 - 2007/09/28
7
+
8
+ * return PID of the child process
9
+ * added ":detach => false" option
10
+
11
+ --------------------------------------------------
12
+ v0.3 - 2007/10/15
13
+
14
+ * added ':method => :thread' for threaded spawns
15
+ * removed ':detach => false' option in favor of more generic implementation
16
+ * added ability to set configuration of the form 'Spawn::method :thread'
17
+ * added patch to ActiveRecord::Base to allow for more efficient reconnect in child processes
18
+ * added monkey patch for http://dev.rubyonrails.org/ticket/7579
19
+ * added wait() method to wait for spawned code blocks
20
+ * don't allow threading if allow_concurrency=false
21
+
22
+ --------------------------------------------------
23
+ v0.4 - 2008/1/26
24
+
25
+ * default to :thread on windows, still :fork on all other platforms
26
+ * raise exception when used with :method=>:true and allow_concurrency != true
27
+
28
+ --------------------------------------------------
29
+ v0.5 - 2008/3/1
30
+ * also default to :thread on JRuby (java)
31
+ * added new :method => :yield which doesn't fork or thread, this is useful for testing
32
+ * fixed problem with connections piling up on PostgreSQL
33
+
34
+ --------------------------------------------------
35
+ v0.6 - 2008/04/21
36
+ * only apply clear_reloadable_connections patch on Rails 1.x (7579 fixed in Rails 2.x)
37
+ * made it more responsive in more environments by disconnecting from the listener socket in the forked process
38
+
39
+ --------------------------------------------------
40
+ v0.7 - 2008/04/24
41
+ * more generic mechanism for closing resources after fork
42
+ * check for existence of Mongrel before patching it
43
+
44
+ --------------------------------------------------
45
+ v0.8 - 2008/05/02
46
+ * call exit! within the ensure block so that at_exit handlers aren't called on exceptions
47
+ * set logger from RAILS_DEFAULT_LOGGER if available, else STDERR
48
+
49
+ --------------------------------------------------
50
+ v0.9 - 2008/05/11
51
+ * added ability to set nice level for child process
52
+
53
+ --------------------------------------------------
54
+ v1.0 - 2010/10/09
55
+ * merged edged to master, let's call this version 1.0
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2007 Tom Anderson (tom@squeat.com)
2
+
3
+ Permission is hereby granted, free of charge, to any person
4
+ obtaining a copy of this software and associated documentation
5
+ files (the "Software"), to deal in the Software without
6
+ restriction, including without limitation the rights to use,
7
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the
9
+ Software is furnished to do so, subject to the following
10
+ conditions:
11
+
12
+ The above copyright notice and this permission notice shall be
13
+ included in all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22
+ OTHER DEALINGS IN THE SOFTWARE.
data/README.markdown ADDED
@@ -0,0 +1,193 @@
1
+ # Spawn
2
+
3
+ This plugin provides a 'spawn' method to easily fork OR thread long-running sections of
4
+ code so that your application can return results to your users more quickly.
5
+ This plugin works by creating new database connections in ActiveRecord::Base for the
6
+ spawned block.
7
+
8
+ The plugin also patches ActiveRecord::Base to handle some known bugs when using
9
+ threads (see lib/patches.rb).
10
+
11
+ ## Installation
12
+
13
+ To install the plugin from the master branch (recommended).
14
+
15
+ script/plugin install git://github.com/tra/spawn.git
16
+
17
+ If you want to install the plugin from the 'edge' branch (latest development):
18
+
19
+ script/plugin install git://github.com/tra/spawn.git -r edge
20
+
21
+ If you are unfortunate enough to be stuck on Rails 1.x, then it is recommended you
22
+ stick with v1.0 of this plugin (Rails 1.x won't be supported in future versions but
23
+ it might still work if you're lucky). To install this version:
24
+
25
+ script/plugin install git://github.com/tra/spawn.git -r master:v1.0
26
+
27
+ ## Usage
28
+
29
+ Here's a simple example of how to demonstrate the spawn plugin.
30
+ In one of your controllers, insert this code (after installing the plugin of course):
31
+
32
+ spawn do
33
+ logger.info("I feel sleepy...")
34
+ sleep 11
35
+ logger.info("Time to wake up!")
36
+ end
37
+
38
+ If everything is working correctly, your controller should finish quickly then you'll see
39
+ the last log message several seconds later.
40
+
41
+ If you need to wait for the spawned processes/threads, then pass the objects returned by
42
+ spawn to Spawn::wait(), like this:
43
+
44
+ N.times do |i|
45
+ # spawn N blocks of code
46
+ spawn_ids[i] = spawn do
47
+ something(i)
48
+ end
49
+ end
50
+ # wait for all N blocks of code to finish running
51
+ wait(spawn_ids)
52
+
53
+ ## Options
54
+
55
+ The options you can pass to spawn are:
56
+
57
+ <table>
58
+ <tr><th>Option</th><th>Values</th></tr>
59
+ <tr><td>:method</td><td>:fork, :thread, :yield</td></tr>
60
+ <tr><td>:nice</td><td>integer value 0-19, 19 = really nice</td></tr>
61
+ <tr><td>:kill</td><td>boolean value indicating whether the parent should kill the spawned process
62
+ when it exits (only valid when :method => :fork)</td></tr>
63
+ <tr><td>:argv</td><td>string to override the process name</td></tr>
64
+ </table>
65
+
66
+ Any option to spawn can be set as a default so that you don't have to pass them in
67
+ to every call of spawn. To configure the spawn default options, add a line to
68
+ your configuration file(s) like this:
69
+
70
+ Spawn::default_options {:method => :thread}
71
+
72
+ If you don't set any default options, the :method will default to :fork. To
73
+ specify different values for different environments, add the default_options call to
74
+ he appropriate environment file (development.rb, test.rb). For testing you can set
75
+ the default :method to :yield so that the code is run inline.
76
+
77
+ # in environment.rb
78
+ Spawn::method :method => :fork, :nice => 7
79
+ # in test.rb, will override the environment.rb setting
80
+ Spawn::method :method => :yield
81
+
82
+ This allows you to set your production and development environments to use different
83
+ methods according to your needs.
84
+
85
+ ### be nice
86
+
87
+ If you want your forked child to run at a lower priority than the parent process, pass in
88
+ the :nice option like this:
89
+
90
+ spawn(:nice => 7) do
91
+ do_something_nicely
92
+ end
93
+
94
+ ### fork me
95
+
96
+ By default, spawn will use the fork to spawn child processes. You can configure it to
97
+ do threading either by telling the spawn method when you call it or by configuring your
98
+ environment.
99
+ For example, this is how you can tell spawn to use threading on the call,
100
+
101
+ spawn(:method => :thread) do
102
+ something
103
+ end
104
+
105
+ For older versions of Rails (1.x), when using the :thread setting, spawn will check to
106
+ make sure that you have set allow_concurrency=true in your configuration. If you
107
+ want this setting then put this line in one of your environment config files:
108
+
109
+ config.active_record.allow_concurrency = true
110
+
111
+ If it is not set, then spawn will raise an exception.
112
+
113
+ ### kill or be killed
114
+
115
+ Depending on your application, you may want the children processes to go away when
116
+ the parent process exits. By default spawn lets the children live after the
117
+ parent dies. But you can tell it to kill the children by setting the :kill option
118
+ to true.
119
+
120
+ ### a process by any other name
121
+
122
+ If you'd like to be able to identify which processes are spawned by looking at the
123
+ output of ps then set the :argv option with a string of your choice.
124
+ You should then be able to see this string as the process name when
125
+ listing the running processes (ps).
126
+
127
+ For example, if you do something like this,
128
+
129
+ 3.times do |i|
130
+ spawn(:argv => "spawn -#{i}-") do
131
+ something(i)
132
+ end
133
+ end
134
+
135
+ then in the shell,
136
+
137
+ $ ps -ef | grep spawn
138
+ 502 2645 2642 0 0:00.01 ttys002 0:00.02 spawn -0-
139
+ 502 2646 2642 0 0:00.02 ttys002 0:00.02 spawn -1-
140
+ 502 2647 2642 0 0:00.02 ttys002 0:00.03 spawn -2-
141
+
142
+ The length of the process name may be limited by your OS so you might want to experiment
143
+ to see how long it can be (it may be limited by the length of the original process name).
144
+
145
+ ## Forking vs. Threading
146
+
147
+ There are several tradeoffs for using threading vs. forking. Forking was chosen as the
148
+ default primarily because it requires no configuration to get it working out of the box.
149
+
150
+ Forking advantages:
151
+
152
+ - more reliable? - the ActiveRecord code is generally not deemed to be thread-safe.
153
+ Even though spawn attempts to patch known problems with the threaded implementation,
154
+ there are no guarantees. Forking is heavier but should be fairly reliable.
155
+ - keep running - this could also be a disadvantage, but you may find you want to fork
156
+ off a process that could have a life longer than its parent. For example, maybe you
157
+ want to restart your server without killing the spawned processes.
158
+ We don't necessarily condone this (i.e. haven't tried it) but it's technically possible.
159
+ - easier - forking works out of the box with spawn, threading requires you set
160
+ allow_concurrency=true (for older versions of Rails).
161
+ Also, beware of automatic reloading of classes in development
162
+ mode (config.cache_classes = false).
163
+
164
+ Threading advantages:
165
+ - less filling - threads take less resources... how much less? it depends. Some
166
+ flavors of Unix are pretty efficient at forking so the threading advantage may not
167
+ be as big as you think... but then again, maybe it's more than you think. ;-)
168
+ - debugging - you can set breakpoints in your threads
169
+
170
+ ## Acknowledgements
171
+
172
+ This plugin was initially inspired by Scott Persinger's blog post on how to use fork
173
+ in rails for background processing.
174
+ http://geekblog.vodpod.com/?p=26
175
+
176
+ Further inspiration for the threading implementation came from Jonathon Rochkind's
177
+ blog post on threading in rails.
178
+ http://bibwild.wordpress.com/2007/08/28/threading-in-rails/
179
+
180
+ Also thanks to all who have helped debug problems and suggest improvements
181
+ including:
182
+
183
+ - Ahmed Adam, Tristan Schneiter, Scott Haug, Andrew Garfield, Eugene Otto, Dan Sharp,
184
+ Olivier Ruffin, Adrian Duyzer, Cyrille Labesse
185
+
186
+ - Garry Tan, Matt Jankowski (Rails 2.2.x fixes), Mina Naguib (Rails 2.3.6 fix)
187
+
188
+ - Tim Kadom, Mauricio Marcon Zaffari, Danial Pearce, Hongli Lai, Scott Wadden
189
+ (passenger fixes)
190
+
191
+ - &lt;your name here&gt;
192
+
193
+ Copyright (c) 2007-present Tom Anderson (tom@squeat.com), see LICENSE
data/lib/spawn.rb ADDED
@@ -0,0 +1,6 @@
1
+ require File.join(File.dirname(__FILE__), 'spawn', 'spawn')
2
+ require File.join(File.dirname(__FILE__), 'spawn', 'patches')
3
+
4
+ ActiveRecord::Base.send :include, Spawn
5
+ ActionController::Base.send :include, Spawn
6
+ ActiveRecord::Observer.send :include, Spawn
@@ -0,0 +1,109 @@
1
+ # see activerecord/lib/active_record/connection_adaptors/abstract/connection_specification.rb
2
+ class ActiveRecord::Base
3
+ # reconnect without disconnecting
4
+ if Spawn::RAILS_2_2
5
+ def self.spawn_reconnect(klass=self)
6
+ # keep ancestors' connection_handlers around to avoid them being garbage collected in the forked child
7
+ @@ancestor_connection_handlers ||= []
8
+ @@ancestor_connection_handlers << self.connection_handler
9
+ self.connection_handler = ActiveRecord::ConnectionAdapters::ConnectionHandler.new
10
+
11
+ establish_connection
12
+ end
13
+ else
14
+ def self.spawn_reconnect(klass=self)
15
+ spec = @@defined_connections[klass.name]
16
+ konn = active_connections[klass.name]
17
+ # remove from internal arrays before calling establish_connection so that
18
+ # the connection isn't disconnected when it calls AR::Base.remove_connection
19
+ @@defined_connections.delete_if { |key, value| value == spec }
20
+ active_connections.delete_if { |key, value| value == konn }
21
+ establish_connection(spec ? spec.config : nil)
22
+ end
23
+ end
24
+
25
+ # this patch not needed on Rails 2.x and later
26
+ if Spawn::RAILS_1_x
27
+ # monkey patch to fix threading problems,
28
+ # see: http://dev.rubyonrails.org/ticket/7579
29
+ def self.clear_reloadable_connections!
30
+ if @@allow_concurrency
31
+ # Hash keyed by thread_id in @@active_connections. Hash of hashes.
32
+ @@active_connections.each do |thread_id, conns|
33
+ conns.each do |name, conn|
34
+ if conn.requires_reloading?
35
+ conn.disconnect!
36
+ @@active_connections[thread_id].delete(name)
37
+ end
38
+ end
39
+ end
40
+ else
41
+ # Just one level hash, no concurrency.
42
+ @@active_connections.each do |name, conn|
43
+ if conn.requires_reloading?
44
+ conn.disconnect!
45
+ @@active_connections.delete(name)
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+
53
+ # see mongrel/lib/mongrel.rb
54
+ # it's possible that this is not defined if you're running outside of mongrel
55
+ # examples: ./script/runner or ./script/console
56
+ if defined? Mongrel::HttpServer
57
+ class Mongrel::HttpServer
58
+ # redefine Montrel::HttpServer::process_client so that we can intercept
59
+ # the socket that is being used so Spawn can close it upon forking
60
+ alias_method :orig_process_client, :process_client
61
+ def process_client(client)
62
+ Spawn.resources_to_close(client, @socket)
63
+ orig_process_client(client)
64
+ end
65
+ end
66
+ end
67
+
68
+ need_passenger_patch = true
69
+ if defined? PhusionPassenger::VERSION_STRING
70
+ # The VERSION_STRING variable was defined sometime after 2.1.0.
71
+ # We don't need passenger patch for 2.2.2 or later.
72
+ pv = PhusionPassenger::VERSION_STRING.split('.').collect{|s| s.to_i}
73
+ need_passenger_patch = pv[0] < 2 || (pv[0] == 2 && (pv[1] < 2 || (pv[1] == 2 && pv[2] < 2)))
74
+ end
75
+
76
+ if need_passenger_patch
77
+ # Patch for work with passenger < 2.1.0
78
+ if defined? Passenger::Railz::RequestHandler
79
+ class Passenger::Railz::RequestHandler
80
+ alias_method :orig_process_request, :process_request
81
+ def process_request(headers, input, output)
82
+ Spawn.resources_to_close(input, output)
83
+ orig_process_request(headers, input, output)
84
+ end
85
+ end
86
+ end
87
+
88
+ # Patch for work with passenger >= 2.1.0
89
+ if defined? PhusionPassenger::Railz::RequestHandler
90
+ class PhusionPassenger::Railz::RequestHandler
91
+ alias_method :orig_process_request, :process_request
92
+ def process_request(headers, input, output)
93
+ Spawn.resources_to_close(input, output)
94
+ orig_process_request(headers, input, output)
95
+ end
96
+ end
97
+ end
98
+
99
+ # Patch for passenger with Rails >= 2.3.0 (uses rack)
100
+ if defined? PhusionPassenger::Rack::RequestHandler
101
+ class PhusionPassenger::Rack::RequestHandler
102
+ alias_method :orig_process_request, :process_request
103
+ def process_request(headers, input, output)
104
+ Spawn.resources_to_close(input, output)
105
+ orig_process_request(headers, input, output)
106
+ end
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,211 @@
1
+ module Spawn
2
+ RAILS_1_x = (::Rails::VERSION::MAJOR == 1) unless defined?(RAILS_1_x)
3
+ RAILS_2_2 = (::Rails::VERSION::MAJOR > 2 || (::Rails::VERSION::MAJOR == 2 && ::Rails::VERSION::MINOR >= 2)) unless defined?(RAILS_2_2)
4
+
5
+ @@default_options = {
6
+ # default to forking (unless windows or jruby)
7
+ :method => ((RUBY_PLATFORM =~ /(win32|java)/) ? :thread : :fork),
8
+ :nice => nil,
9
+ :kill => false,
10
+ :argv => nil
11
+ }
12
+
13
+ # things to close in child process
14
+ @@resources = []
15
+ # in some environments, logger isn't defined
16
+ @@logger = defined?(RAILS_DEFAULT_LOGGER) ? RAILS_DEFAULT_LOGGER : Logger.new(STDERR)
17
+ # forked children to kill on exit
18
+ @@punks = []
19
+
20
+ # Set the options to use every time spawn is called unless specified
21
+ # otherwise. For example, in your environment, do something like
22
+ # this:
23
+ # Spawn::default_options = {:nice => 5}
24
+ # to default to using the :nice option with a value of 5 on every call.
25
+ # Valid options are:
26
+ # :method => (:thread | :fork | :yield)
27
+ # :nice => nice value of the forked process
28
+ # :kill => whether or not the parent process will kill the
29
+ # spawned child process when the parent exits
30
+ # :argv => changes name of the spawned process as seen in ps
31
+ def self.default_options(options = {})
32
+ @@default_options.merge!(options)
33
+ @@logger.info "spawn> default options = #{options.inspect}"
34
+ end
35
+
36
+ # @deprecated - please use Spawn::default_options(:method => ) instead
37
+ # add calls to this in your environment.rb to set your configuration, for example,
38
+ # to use forking everywhere except your 'development' environment:
39
+ # Spawn::method :fork
40
+ # Spawn::method :thread, 'development'
41
+ def self.method(method, env = nil)
42
+ @@logger.warn "spawn> please use Spawn::default_options(:method => #{method}) instead of Spawn::method"
43
+ if !env || env == RAILS_ENV
44
+ default_options :method => method
45
+ end
46
+ end
47
+
48
+ # set the resources to disconnect from in the child process (when forking)
49
+ def self.resources_to_close(*resources)
50
+ @@resources = resources
51
+ end
52
+
53
+ # close all the resources added by calls to resource_to_close
54
+ def self.close_resources
55
+ @@resources.each do |resource|
56
+ resource.close if resource && resource.respond_to?(:close) && !resource.closed?
57
+ end
58
+ # in case somebody spawns recursively
59
+ @@resources.clear
60
+ end
61
+
62
+ def self.alive?(pid)
63
+ begin
64
+ Process::kill 0, pid
65
+ # if the process is alive then kill won't throw an exception
66
+ true
67
+ rescue Errno::ESRCH
68
+ false
69
+ end
70
+ end
71
+
72
+ def self.kill_punks
73
+ @@punks.each do |punk|
74
+ if alive?(punk)
75
+ @@logger.info "spawn> parent(#{Process.pid}) killing child(#{punk})"
76
+ begin
77
+ Process.kill("TERM", punk)
78
+ rescue
79
+ end
80
+ end
81
+ end
82
+ @@punks = []
83
+ end
84
+ # register to kill marked children when parent exits
85
+ at_exit {kill_punks}
86
+
87
+ # Spawns a long-running section of code and returns the ID of the spawned process.
88
+ # By default the process will be a forked process. To use threading, pass
89
+ # :method => :thread or override the default behavior in the environment by setting
90
+ # 'Spawn::method :thread'.
91
+ def spawn(opts = {})
92
+ options = @@default_options.merge(opts.symbolize_keys)
93
+ # setting options[:method] will override configured value in default_options[:method]
94
+ if options[:method] == :yield
95
+ yield
96
+ elsif options[:method] == :thread
97
+ # for versions before 2.2, check for allow_concurrency
98
+ if RAILS_2_2 || ActiveRecord::Base.allow_concurrency
99
+ thread_it(options) { yield }
100
+ else
101
+ @@logger.error("spawn(:method=>:thread) only allowed when allow_concurrency=true")
102
+ raise "spawn requires config.active_record.allow_concurrency=true when used with :method=>:thread"
103
+ end
104
+ else
105
+ fork_it(options) { yield }
106
+ end
107
+ end
108
+
109
+ def wait(sids = [])
110
+ # wait for all threads and/or forks (if a single sid passed in, convert to array first)
111
+ Array(sids).each do |sid|
112
+ if sid.type == :thread
113
+ sid.handle.join()
114
+ else
115
+ begin
116
+ Process.wait(sid.handle)
117
+ rescue
118
+ # if the process is already done, ignore the error
119
+ end
120
+ end
121
+ end
122
+ # clean up connections from expired threads
123
+ ActiveRecord::Base.verify_active_connections!()
124
+ end
125
+
126
+ class SpawnId
127
+ attr_accessor :type
128
+ attr_accessor :handle
129
+ def initialize(t, h)
130
+ self.type = t
131
+ self.handle = h
132
+ end
133
+ end
134
+
135
+ protected
136
+ def fork_it(options)
137
+ # The problem with rails is that it only has one connection (per class),
138
+ # so when we fork a new process, we need to reconnect.
139
+ @@logger.debug "spawn> parent PID = #{Process.pid}"
140
+ child = fork do
141
+ begin
142
+ start = Time.now
143
+ @@logger.debug "spawn> child PID = #{Process.pid}"
144
+
145
+ # this child has no children of it's own to kill (yet)
146
+ @@punks = []
147
+
148
+ # set the nice priority if needed
149
+ Process.setpriority(Process::PRIO_PROCESS, 0, options[:nice]) if options[:nice]
150
+
151
+ # disconnect from the listening socket, et al
152
+ Spawn.close_resources
153
+ # get a new connection so the parent can keep the original one
154
+ ActiveRecord::Base.spawn_reconnect
155
+
156
+ # set the process name
157
+ $0 = options[:argv] if options[:argv]
158
+
159
+ # run the block of code that takes so long
160
+ yield
161
+
162
+ rescue => ex
163
+ @@logger.error "spawn> Exception in child[#{Process.pid}] - #{ex.class}: #{ex.message}"
164
+ ensure
165
+ begin
166
+ # to be safe, catch errors on closing the connnections too
167
+ if RAILS_2_2
168
+ ActiveRecord::Base.connection_handler.clear_all_connections!
169
+ else
170
+ ActiveRecord::Base.connection.disconnect!
171
+ ActiveRecord::Base.remove_connection
172
+ end
173
+ ensure
174
+ @@logger.info "spawn> child[#{Process.pid}] took #{Time.now - start} sec"
175
+ # ensure log is flushed since we are using exit!
176
+ @@logger.flush if @@logger.respond_to?(:flush)
177
+ # this child might also have children to kill if it called spawn
178
+ Spawn::kill_punks
179
+ # this form of exit doesn't call at_exit handlers
180
+ exit!(0)
181
+ end
182
+ end
183
+ end
184
+
185
+ # detach from child process (parent may still wait for detached process if they wish)
186
+ Process.detach(child)
187
+
188
+ # remove dead children from the target list to avoid memory leaks
189
+ @@punks.delete_if {|punk| !Spawn::alive?(punk)}
190
+
191
+ # mark this child for death when this process dies
192
+ if options[:kill]
193
+ @@punks << child
194
+ @@logger.debug "spawn> death row = #{@@punks.inspect}"
195
+ end
196
+
197
+ return SpawnId.new(:fork, child)
198
+ end
199
+
200
+ def thread_it(options)
201
+ # clean up stale connections from previous threads
202
+ ActiveRecord::Base.verify_active_connections!()
203
+ thr = Thread.new do
204
+ # run the long-running code block
205
+ yield
206
+ end
207
+ thr.priority = -options[:nice] if options[:nice]
208
+ return SpawnId.new(:thread, thr)
209
+ end
210
+
211
+ end
@@ -0,0 +1,15 @@
1
+ $:.push File.expand_path("../lib", __FILE__)
2
+
3
+ Gem::Specification.new do |gem|
4
+ gem.name = 'tlconnor-spawn'
5
+ gem.version = '1.0.0'
6
+ gem.platform = Gem::Platform::RUBY
7
+ gem.authors = ['Tim Connor']
8
+ gem.email = 'tlconnor@gmail.com'
9
+ gem.summary = 'Spawn'
10
+ gem.description = gem.summary
11
+
12
+ gem.files = `git ls-files`.split("\n")
13
+ gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
14
+ gem.require_paths = ["lib"]
15
+ end
metadata ADDED
@@ -0,0 +1,74 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tlconnor-spawn
3
+ version: !ruby/object:Gem::Version
4
+ hash: 23
5
+ prerelease:
6
+ segments:
7
+ - 1
8
+ - 0
9
+ - 0
10
+ version: 1.0.0
11
+ platform: ruby
12
+ authors:
13
+ - Tim Connor
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2012-03-09 00:00:00 +13:00
19
+ default_executable:
20
+ dependencies: []
21
+
22
+ description: Spawn
23
+ email: tlconnor@gmail.com
24
+ executables: []
25
+
26
+ extensions: []
27
+
28
+ extra_rdoc_files: []
29
+
30
+ files:
31
+ - .gitignore
32
+ - CHANGELOG
33
+ - LICENSE
34
+ - README.markdown
35
+ - lib/spawn.rb
36
+ - lib/spawn/patches.rb
37
+ - lib/spawn/spawn.rb
38
+ - tlconnor-spawn.gemspec
39
+ has_rdoc: true
40
+ homepage:
41
+ licenses: []
42
+
43
+ post_install_message:
44
+ rdoc_options: []
45
+
46
+ require_paths:
47
+ - lib
48
+ required_ruby_version: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ hash: 3
54
+ segments:
55
+ - 0
56
+ version: "0"
57
+ required_rubygems_version: !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ hash: 3
63
+ segments:
64
+ - 0
65
+ version: "0"
66
+ requirements: []
67
+
68
+ rubyforge_project:
69
+ rubygems_version: 1.6.2
70
+ signing_key:
71
+ specification_version: 3
72
+ summary: Spawn
73
+ test_files: []
74
+