Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove daemonization #2170

Merged
merged 2 commits into from Mar 10, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions History.md
Expand Up @@ -13,6 +13,7 @@
* `--control` has been removed. Use `--control-url` (#1487)
* `worker_directory` has been removed. Use `directory`.
* `tcp_mode` has been removed without replacement. (#2169)
* Daemonization has been removed without replacement. (#2170)
* Changed #connected_port to #connected_ports (#2076)

* Bugfixes
Expand Down
2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -270,7 +270,7 @@ It is common to use process monitors with Puma. Modern process monitors like sys
provide continuous monitoring and restarts for increased
reliability in production environments:

* [tools/jungle](https://github.com/puma/puma/tree/master/tools/jungle) for sysvinit (init.d) and upstart
* [docs/jungle](https://github.com/puma/puma/tree/master/docs/jungle) for rc.d and upstart
* [docs/systemd](https://github.com/puma/puma/blob/master/docs/systemd.md)

## Community Extensions
Expand Down
4 changes: 3 additions & 1 deletion docs/deployment.md
Expand Up @@ -74,7 +74,9 @@ thread to become available.
* haproxy: `%Th` (TLS handshake time) and `%Ti` (idle time before request) can
can also be added as headers.

## Daemonizing
## Should I daemonize?

Daemonization was removed in Puma 5.0. For alternatives, continue reading.

I prefer to not daemonize my servers and use something like `runit` or `upstart` to
monitor them as child processes. This gives them fast response to crashes and
Expand Down
13 changes: 13 additions & 0 deletions docs/jungle/README.md
@@ -0,0 +1,13 @@
# Puma as a service

## Upstart

See `/docs/jungle/upstart` for Ubuntu's upstart scripts.

## Systemd

See [/docs/systemd](https://github.com/puma/puma/blob/master/docs/systemd.md).

## rc.d

See `/docs/jungle/rc.d` for FreeBSD's rc.d scripts
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
60 changes: 0 additions & 60 deletions docs/systemd.md
Expand Up @@ -209,66 +209,6 @@ Apr 07 08:40:19 hx puma[28320]: * Activated ssl://0.0.0.0:9234?key=key.pem&cert=
Apr 07 08:40:19 hx puma[28320]: Use Ctrl-C to stop
~~~~

## Alternative Forking Configuration

Other systems/tools might expect or need puma to be run as a
"traditional" forking server, for example so that the `pumactl`
command can be used directly and outside of systemd for
stop/start/restart. This use case is incompatible with systemd socket
activation, so it should not be configured. Below is an alternative
puma.service config sample, using `Type=forking` and the `--daemon`
flag in `ExecStart`. Here systemd is playing a role more equivalent to
SysV init.d, where it is responsible for starting Puma on boot
(multi-user.target) and stopping it on shutdown, but is not performing
continuous restarts. Therefore running Puma in cluster mode, where the
master can restart workers, is highly recommended. See the systemd
[Restart] directive for details.

~~~~ ini
[Unit]
Description=Puma HTTP Forking Server
After=network.target

[Service]
# Background process configuration (use with --daemon in ExecStart)
Type=forking

# Preferably configure a non-privileged user
# User=

# The path to the puma application root
# Also replace the "<WD>" place holders below with this path.
WorkingDirectory=

# The command to start Puma
# (replace "<WD>" below)
ExecStart=bundle exec puma -C <WD>/shared/puma.rb --daemon

# The command to stop Puma
# (replace "<WD>" below)
ExecStop=bundle exec pumactl -S <WD>/shared/tmp/pids/puma.state stop

# Path to PID file so that systemd knows which is the master process
PIDFile=<WD>/shared/tmp/pids/puma.pid

# Should systemd restart puma?
# Use "no" (the default) to ensure no interference when using
# stop/start/restart via `pumactl`. The "on-failure" setting might
# work better for this purpose, but you must test it.
# Use "always" if only `systemctl` is used for start/stop/restart, and
# reconsider if you actually need the forking config.
Restart=no

# `puma_ctl restart` wouldn't work without this. It's because `pumactl`
# changes PID on restart and systemd stops the service afterwards
# because of the PID change. This option prevents stopping after PID
# change.
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target
~~~~

### capistrano3-puma

By default,
Expand Down
5 changes: 0 additions & 5 deletions lib/puma/cli.rb
Expand Up @@ -117,11 +117,6 @@ def setup_options
@control_options[:auth_token] = arg
end

o.on "-d", "--daemon", "Daemonize the server into the background" do
user_config.daemonize
user_config.quiet
end

o.on "--debug", "Log lowlevel debugging information" do
user_config.debug
end
Expand Down
7 changes: 1 addition & 6 deletions lib/puma/cluster.rb
Expand Up @@ -469,12 +469,7 @@ def run
#
@check_pipe, @suicide_pipe = Puma::Util.pipe

if daemon?
log "* Daemonizing..."
Process.daemon(true)
else
log "Use Ctrl-C to stop"
end
log "Use Ctrl-C to stop"

redirect_io

Expand Down
1 change: 0 additions & 1 deletion lib/puma/configuration.rb
Expand Up @@ -175,7 +175,6 @@ def puma_default_options
:debug => false,
:binds => ["tcp://#{DefaultTCPHost}:#{DefaultTCPPort}"],
:workers => 0,
:daemon => false,
:mode => :http,
:worker_timeout => DefaultWorkerTimeout,
:worker_boot_timeout => DefaultWorkerTimeout,
Expand Down
14 changes: 0 additions & 14 deletions lib/puma/dsl.rb
Expand Up @@ -210,20 +210,6 @@ def clean_thread_locals(which=true)
@options[:clean_thread_locals] = which
end

# Daemonize the server into the background. It's highly recommended to
# use this in combination with +pidfile+ and +stdout_redirect+.
#
# The default is "false".
#
# @example
# daemonize
#
# @example
# daemonize false
def daemonize(which=true)
@options[:daemon] = which
end

# When shutting down, drain the accept socket of pending
# connections and process them. This loops over the accept
# socket until there are no more read events and then stops
Expand Down
58 changes: 0 additions & 58 deletions lib/puma/jruby_restart.rb
Expand Up @@ -22,63 +22,5 @@ def self.chdir_exec(dir, argv)
execlp(cmd, *argv)
raise SystemCallError.new(FFI.errno)
end

PermKey = 'PUMA_DAEMON_PERM'
RestartKey = 'PUMA_DAEMON_RESTART'

# Called to tell things "Your now always in daemon mode,
# don't try to reenter it."
#
def self.perm_daemonize
ENV[PermKey] = "1"
end

def self.daemon?
ENV.key?(PermKey) || ENV.key?(RestartKey)
end

def self.daemon_init
return true if ENV.key?(PermKey)

return false unless ENV.key? RestartKey

master = ENV[RestartKey]

# In case the master disappears early
begin
Process.kill "SIGUSR2", master.to_i
rescue SystemCallError => e
end

ENV[RestartKey] = ""

setsid

null = File.open "/dev/null", "w+"
STDIN.reopen null
STDOUT.reopen null
STDERR.reopen null

true
end

def self.daemon_start(dir, argv)
ENV[RestartKey] = Process.pid.to_s

if k = ENV['PUMA_JRUBY_DAEMON_OPTS']
ENV['JRUBY_OPTS'] = k
end

cmd = argv.first
argv = ([:string] * argv.size).zip(argv).flatten
argv << :string
argv << nil

chdir(dir)
ret = fork
return ret if ret != 0
execlp(cmd, *argv)
raise SystemCallError.new(FFI.errno)
end
end
end
4 changes: 0 additions & 4 deletions lib/puma/launcher.rb
Expand Up @@ -70,10 +70,6 @@ def initialize(conf, launcher_args={})
unsupported "worker mode not supported on #{RUBY_ENGINE} on this platform"
end

if @options[:daemon] && Puma.windows?
unsupported 'daemon mode not supported on Windows'
end

Dir.chdir(@restart_dir)

prune_bundler if prune_bundler?
Expand Down
4 changes: 0 additions & 4 deletions lib/puma/rack/builder.rb
Expand Up @@ -67,10 +67,6 @@ def parse!(args)
options[:environment] = e
}

opts.on("-D", "--daemonize", "run daemonized in the background") { |d|
options[:daemonize] = d ? true : false
}

opts.on("-P", "--pid FILE", "file to store PID") { |f|
options[:pid] = ::File.expand_path(f)
}
Expand Down
5 changes: 0 additions & 5 deletions lib/puma/runner.rb
Expand Up @@ -18,10 +18,6 @@ def initialize(cli, events)
@started_at = Time.now
end

def daemon?
@options[:daemon]
end

def development?
@options[:environment] == "development"
end
Expand Down Expand Up @@ -130,7 +126,6 @@ def load_and_bind
exit 1
end

# Load the app before we daemonize.
begin
@app = @launcher.config.app
rescue Exception => e
Expand Down
63 changes: 4 additions & 59 deletions lib/puma/single.rb
Expand Up @@ -42,64 +42,10 @@ def stop_blocked
@server.stop(true) if @server
end

def jruby_daemon?
daemon? and Puma.jruby?
end

def jruby_daemon_start
require 'puma/jruby_restart'
JRubyRestart.daemon_start(@restart_dir, @launcher.restart_args)
end

def run
already_daemon = false

if jruby_daemon?
require 'puma/jruby_restart'

if JRubyRestart.daemon?
# load and bind before redirecting IO so errors show up on stdout/stderr
load_and_bind
redirect_io
end

already_daemon = JRubyRestart.daemon_init
end

output_header "single"

if jruby_daemon?
if already_daemon
JRubyRestart.perm_daemonize
else
pid = nil

Signal.trap "SIGUSR2" do
log "* Started new process #{pid} as daemon..."

# Must use exit! so we don't unwind and run the ensures
# that will be run by the new child (such as deleting the
# pidfile)
exit!(true)
end

Signal.trap "SIGCHLD" do
log "! Error starting new process as daemon, exiting"
exit 1
end

jruby_daemon_start
sleep
end
else
if daemon?
log "* Daemonizing..."
Process.daemon(true)
redirect_io
end

load_and_bind
end
load_and_bind

Plugins.fire_background

Expand All @@ -109,10 +55,9 @@ def run

@server = server = start_server

unless daemon?
log "Use Ctrl-C to stop"
redirect_io
end

log "Use Ctrl-C to stop"
redirect_io

@launcher.events.fire_on_booted!

Expand Down
2 changes: 1 addition & 1 deletion test/shell/t2.rb
@@ -1,4 +1,4 @@
system "ruby -rrubygems -Ilib bin/pumactl -F test/shell/t2_conf.rb start"
system "ruby -rrubygems -Ilib bin/pumactl -F test/shell/t2_conf.rb start &"
sleep 5
system "curl http://localhost:10103/"

Expand Down
1 change: 0 additions & 1 deletion test/shell/t2_conf.rb
Expand Up @@ -3,4 +3,3 @@
pidfile "t2-pid"
bind "tcp://0.0.0.0:10103"
rackup File.expand_path('../rackup/hello.ru', File.dirname(__FILE__))
daemonize
File renamed without changes.
19 changes: 0 additions & 19 deletions tools/jungle/README.md

This file was deleted.