Exit the process with the specified status.
status | The exit code of the process. |
:api: private
# File lib/merb-core/rack/adapter/abstract.rb, line 314 314: def self.exit_process(status = 0) 315: exit(status) 316: end
This method is designed to be overridden in a rack adapter. It will be called to create a new instance of the server for the adapter to start. The adapter should attempt to bind to a port at this point. This is called from the AbstractAdapter start method.
port | The port the server should listen on |
:api: plugin @overridable
# File lib/merb-core/rack/adapter/abstract.rb, line 68 68: def self.new_server(port) 69: raise NotImplemented 70: end
Set the process title.
whoami | Either :spawner for the master process or :worker for any of the worker |
processes.
port | The base port that the app is running on. |
:api: private
# File lib/merb-core/rack/adapter/abstract.rb, line 326 326: def self.process_title(whoami, port) 327: name = Merb::Config[:name] 328: app = "merb#{" : #{name}" if (name && name != "merb")}" 329: max_port = Merb::Config[:cluster] ? (Merb::Config[:cluster] - 1) : 0 330: numbers = ((whoami != :worker) && (max_port > 0)) ? "#{port}..#{port + max_port}" : port 331: file = Merb::Config[:socket_file] % port if Merb::Config[:socket_file] 332: 333: listening_on = if Merb::Config[:socket] 334: "socket#{'s' if max_port > 0 && whoami != :worker} #{numbers} " "#{file ? file : "#{Merb.log_path}/#{name}.#{port}.sock"}" 335: else 336: "port#{'s' if max_port > 0 && whoami != :worker} #{port}" 337: end 338: "#{app} : #{whoami} (#{listening_on})" 339: end
Spawn a new worker process at a port.
port | The port to start the worker process on. |
:api: private
# File lib/merb-core/rack/adapter/abstract.rb, line 93 93: def self.spawn_worker(port) 94: worker_pid = Kernel.fork 95: 96: # If we have a worker_pid, we're in the parent. 97: if worker_pid.nil? 98: # Seed the random number generator 99: Kernel.srand 100: 101: # Restart the run_later worker, unless we're in the parent or it's alive. 102: Merb::Worker.restart unless Merb::Worker.alive? 103: 104: # Spawn the worker 105: start_at_port(port, @opts) 106: 107: throw(:new_worker) 108: end 109: 110: @pids[port] = worker_pid 111: $WORKERS = @pids.values 112: end
The main start method for bootloaders that support forking. This method launches the adapters which inherit using the new_server and start_server methods. This method should not be overridden in adapters which want to fork.
opts | A hash of options |
socket: the socket to bind to port: the port to bind to cluster: the number
:api: private
# File lib/merb-core/rack/adapter/abstract.rb, line 126 126: def self.start(opts={}) 127: @opts = opts 128: $WORKERS ||= [] 129: parent = nil 130: 131: @pids = {} 132: port = (opts[:socket] || opts[:port]).to_i 133: max_port = Merb::Config[:cluster] ? Merb::Config[:cluster] - 1 : 0 134: 135: # If we only have a single merb, just start it up and dispense with 136: # the spawner/worker setup. 137: if max_port == 0 138: start_at_port(port) 139: return 140: end 141: 142: $0 = process_title(:spawner, port) 143: 144: # For each port, spawn a new worker. The parent will continue in 145: # the loop, while the worker will throw :new_worker and be booted 146: # out of the loop. 147: catch(:new_worker) do 148: 0.upto(max_port) do |i| 149: parent = spawn_worker(port + i) 150: end 151: end 152: 153: # If we're in a worker, we're done. Otherwise, we've completed 154: # setting up workers and now need to watch them. 155: return unless parent 156: 157: # For each worker, set up a thread in the spawner to watch it 158: 0.upto(max_port) do |i| 159: Thread.new do 160: catch(:new_worker) do 161: loop do 162: pid, status = @pids[port + i], nil 163: poller = Merb::System::PortablePoller.new(pid) 164: begin 165: i = 0 166: loop do 167: # Watch for the pid to exit. 168: _, status = Process.wait2(pid, Process::WNOHANG) 169: break if status 170: 171: if (i % 120 == 0) && Merb::Config[:max_memory] && poller.memory > Merb::Config[:max_memory] 172: Process.kill("INT", pid) 173: if (Process.kill(0, pid) rescue false) 174: sleep Merb::Config[:hang_time] || 5 175: Process.kill(9, pid) 176: Process.wait2(pid) if (Process.kill(0, pid) rescue false) 177: end 178: 179: status = Struct.new(:exitstatus).new(nil) 180: break 181: end 182: i += 1 183: sleep 0.25 184: end 185: 186: # If the pid doesn't exist, we want to silently exit instead of 187: # raising here. 188: rescue SystemCallError => e 189: ensure 190: # If there was no worker with that PID, the status was non-0 191: # (we send back a status of 128 when ABRT is called on a 192: # worker, and Merb.fatal! exits with a status of 1), or if 193: # Merb is in the process of exiting, *then* don't respawn. 194: # Note that processes killed with kill -9 will return no 195: # exitstatus, and we respawn them. 196: if !status || 197: (status.exitstatus && status.exitstatus != 0) || 198: Merb.exiting then 199: Thread.exit 200: end 201: end 202: 203: # Otherwise, respawn the worker, and watch it again. 204: spawn_worker(port + i) 205: end 206: end 207: end 208: end 209: 210: # The spawner process will make it here, and when it does, it should just 211: # sleep so it can pick up ctrl-c if it's in console mode. 212: sleep 213: 214: end
Fork a server on the specified port and start the app.
port | The port to start the server on |
opts | The hash of options, defaults to the @opts |
instance variable.
:api: private
# File lib/merb-core/rack/adapter/abstract.rb, line 224 224: def self.start_at_port(port, opts = @opts) 225: at_exit do 226: Merb::Server.remove_pid(port) 227: end 228: 229: # If Merb is daemonized, trap INT. If it's not daemonized, 230: # we let the master process' ctrl-c control the cluster 231: # of workers. 232: if Merb::Config[:daemonize] 233: Merb.trap('INT') do 234: Merb.exiting = true 235: stop 236: Merb.logger.warn! "Exiting port #{port}\n" 237: exit_process 238: end 239: # If it was not fork_for_class_load, we already set up 240: # ctrl-c handlers in the master thread. 241: elsif Merb::Config[:fork_for_class_load] 242: if Merb::Config[:console_trap] 243: Merb::Server.add_irb_trap 244: end 245: end 246: 247: # In daemonized mode or not, support HUPing the process to 248: # restart it. 249: Merb.trap('HUP') do 250: Merb.exiting = true 251: stop 252: Merb.logger.warn! "Exiting port #{port} on #{Process.pid}\n" 253: exit_process 254: end 255: 256: # ABRTing the process will kill it, and it will not be respawned. 257: Merb.trap('ABRT') do 258: Merb.exiting = true 259: stopped = stop(128) 260: Merb.logger.warn! "Exiting port #{port}\n" if stopped 261: exit_process(128) 262: end 263: 264: # Each worker gets its own `ps' name. 265: $0 = process_title(:worker, port) 266: 267: # Store the PID for this worker 268: Merb::Server.store_pid(port) 269: 270: Merb::Config[:log_delimiter] = "#{process_title(:worker, port)} ~ " 271: 272: Merb.reset_logger! 273: Merb.logger.warn!("Starting #{self.name.split("::").last} at port #{port}") 274: 275: # If we can't connect to the port, keep trying until we can. Print 276: # a warning about this once. Try every 0.25s. 277: printed_warning = false 278: loop do 279: begin 280: # Call the adapter's new_server method, which should attempt 281: # to bind to a port. 282: new_server(port) 283: rescue Errno::EADDRINUSE => e 284: if Merb::Config[:bind_fail_fatal] 285: Merb.fatal! "Could not bind to #{port}. It was already in use", e 286: end 287: 288: unless printed_warning 289: Merb.logger.warn! "Port #{port} is in use, " "Waiting for it to become available." 290: printed_warning = true 291: end 292: 293: sleep 0.25 294: next 295: end 296: break 297: end 298: 299: Merb.logger.warn! "Successfully bound to port #{port}" 300: 301: Merb::Server.change_privilege 302: 303: # Call the adapter's start_server method. 304: start_server 305: end
This method is designed to be overridden in a rack adapter. It will be called to start a server created with the new_server method. This is called from the AbstractAdapter start method.
:api: plugin @overridable
# File lib/merb-core/rack/adapter/abstract.rb, line 54 54: def self.start_server 55: raise NotImplemented 56: end
This method is designed to be overridden in a rack adapter. It will be called to stop the adapter server.
status | The exit status the adapter should exit with. |
Boolean | True if the server was properly stopped. |
:api: plugin @overridable
# File lib/merb-core/rack/adapter/abstract.rb, line 83 83: def self.stop(status) 84: raise NotImplemented 85: end
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.