yahns 0.0.0TP1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +15 -0
- data/COPYING +674 -0
- data/GIT-VERSION-GEN +41 -0
- data/GNUmakefile +90 -0
- data/README +127 -0
- data/Rakefile +60 -0
- data/bin/yahns +32 -0
- data/examples/README +3 -0
- data/examples/init.sh +76 -0
- data/examples/logger_mp_safe.rb +28 -0
- data/examples/logrotate.conf +32 -0
- data/examples/yahns_multi.conf.rb +89 -0
- data/examples/yahns_rack_basic.conf.rb +27 -0
- data/lib/yahns.rb +73 -0
- data/lib/yahns/acceptor.rb +28 -0
- data/lib/yahns/client_expire.rb +40 -0
- data/lib/yahns/client_expire_portable.rb +39 -0
- data/lib/yahns/config.rb +344 -0
- data/lib/yahns/daemon.rb +51 -0
- data/lib/yahns/fdmap.rb +90 -0
- data/lib/yahns/http_client.rb +198 -0
- data/lib/yahns/http_context.rb +65 -0
- data/lib/yahns/http_response.rb +184 -0
- data/lib/yahns/log.rb +73 -0
- data/lib/yahns/queue.rb +7 -0
- data/lib/yahns/queue_egg.rb +23 -0
- data/lib/yahns/queue_epoll.rb +57 -0
- data/lib/yahns/rack.rb +80 -0
- data/lib/yahns/server.rb +336 -0
- data/lib/yahns/server_mp.rb +181 -0
- data/lib/yahns/sigevent.rb +7 -0
- data/lib/yahns/sigevent_efd.rb +18 -0
- data/lib/yahns/sigevent_pipe.rb +29 -0
- data/lib/yahns/socket_helper.rb +117 -0
- data/lib/yahns/stream_file.rb +34 -0
- data/lib/yahns/stream_input.rb +150 -0
- data/lib/yahns/tee_input.rb +114 -0
- data/lib/yahns/tmpio.rb +27 -0
- data/lib/yahns/wbuf.rb +36 -0
- data/lib/yahns/wbuf_common.rb +32 -0
- data/lib/yahns/worker.rb +58 -0
- data/test/covshow.rb +29 -0
- data/test/helper.rb +115 -0
- data/test/server_helper.rb +65 -0
- data/test/test_bin.rb +97 -0
- data/test/test_client_expire.rb +132 -0
- data/test/test_config.rb +56 -0
- data/test/test_fdmap.rb +19 -0
- data/test/test_output_buffering.rb +291 -0
- data/test/test_queue.rb +59 -0
- data/test/test_rack.rb +28 -0
- data/test/test_serve_static.rb +42 -0
- data/test/test_server.rb +415 -0
- data/test/test_stream_file.rb +30 -0
- data/test/test_wbuf.rb +136 -0
- data/yahns.gemspec +19 -0
- metadata +165 -0
data/GIT-VERSION-GEN
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
|
3
|
+
# License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
|
4
|
+
CONSTANT = "Yahns::VERSION"
|
5
|
+
RVF = "lib/yahns/version.rb"
|
6
|
+
GVF = "GIT-VERSION-FILE"
|
7
|
+
DEF_VER = "v0.0.0TP1"
|
8
|
+
vn = DEF_VER
|
9
|
+
|
10
|
+
# First see if there is a version file (included in release tarballs),
|
11
|
+
# then try git-describe, then default.
|
12
|
+
if File.exist?(".git")
|
13
|
+
describe = `git describe --abbrev=4 HEAD 2>/dev/null`.strip
|
14
|
+
case describe
|
15
|
+
when /\Av[0-9]*/
|
16
|
+
vn = describe
|
17
|
+
system(*%w(git update-index -q --refresh))
|
18
|
+
unless `git diff-index --name-only HEAD --`.chomp.empty?
|
19
|
+
vn << "-dirty"
|
20
|
+
end
|
21
|
+
vn.tr!('-', '.')
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
vn = vn.sub!(/\Av/, "")
|
26
|
+
new_ruby_version = "#{CONSTANT} = '#{vn}' # :nodoc:\n"
|
27
|
+
cur_ruby_version = File.read(RVF) rescue nil
|
28
|
+
if new_ruby_version != cur_ruby_version
|
29
|
+
File.open(RVF, "w") { |fp| fp.write(new_ruby_version) }
|
30
|
+
end
|
31
|
+
File.chmod(0644, RVF)
|
32
|
+
|
33
|
+
# generate the makefile snippet
|
34
|
+
new_make_version = "VERSION = #{vn}\n"
|
35
|
+
cur_make_version = File.read(GVF) rescue nil
|
36
|
+
if new_make_version != cur_make_version
|
37
|
+
File.open(GVF, "w") { |fp| fp.write(new_make_version) }
|
38
|
+
end
|
39
|
+
File.chmod(0644, GVF)
|
40
|
+
|
41
|
+
puts vn if $0 == __FILE__
|
data/GNUmakefile
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
# Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
|
2
|
+
# License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
|
3
|
+
all::
|
4
|
+
pkg = yahns
|
5
|
+
RUBY = ruby
|
6
|
+
GIT-VERSION-FILE: .FORCE-GIT-VERSION-FILE
|
7
|
+
@./GIT-VERSION-GEN
|
8
|
+
-include GIT-VERSION-FILE
|
9
|
+
lib := lib
|
10
|
+
|
11
|
+
all:: test
|
12
|
+
test_units := $(wildcard test/test_*.rb)
|
13
|
+
test: $(test_units)
|
14
|
+
$(test_units):
|
15
|
+
$(RUBY) -w -I $(lib) $@ -v
|
16
|
+
|
17
|
+
test-mt: export N = $(shell nproc 2>/dev/null || echo 4)
|
18
|
+
test-mt:
|
19
|
+
$(RUBY) -w -I $(lib) $(addprefix -r./,$(test_units)) -eexit --
|
20
|
+
|
21
|
+
check-warnings:
|
22
|
+
@(for i in $$(git ls-files '*.rb'| grep -v '^setup\.rb$$'); \
|
23
|
+
do $(RUBY) -d -W2 -c $$i; done) | grep -v '^Syntax OK$$' || :
|
24
|
+
|
25
|
+
check: test
|
26
|
+
coverage: export COVERAGE=1
|
27
|
+
coverage:
|
28
|
+
> coverage.dump
|
29
|
+
$(MAKE) check
|
30
|
+
$(RUBY) ./test/covshow.rb
|
31
|
+
|
32
|
+
coverage-mt: export COVERAGE=1
|
33
|
+
coverage-mt:
|
34
|
+
> coverage.dump
|
35
|
+
$(MAKE) test-mt
|
36
|
+
$(RUBY) ./test/covshow.rb
|
37
|
+
|
38
|
+
pkggem := pkg/$(pkg)-$(VERSION).gem
|
39
|
+
pkgtgz := pkg/$(pkg)-$(VERSION).tar.gz
|
40
|
+
|
41
|
+
fix-perms:
|
42
|
+
git ls-tree -r HEAD | awk '/^100644 / {print $$NF}' | xargs chmod 644
|
43
|
+
git ls-tree -r HEAD | awk '/^100755 / {print $$NF}' | xargs chmod 755
|
44
|
+
|
45
|
+
gem: $(pkggem)
|
46
|
+
|
47
|
+
install-gem: $(pkggem)
|
48
|
+
gem install $(CURDIR)/$<
|
49
|
+
|
50
|
+
$(pkggem): .gem-manifest
|
51
|
+
VERSION=$(VERSION) gem build $(pkg).gemspec
|
52
|
+
mkdir -p pkg
|
53
|
+
mv $(@F) $@
|
54
|
+
|
55
|
+
pkg_extra := GIT-VERSION-FILE lib/yahns/version.rb NEWS
|
56
|
+
NEWS:
|
57
|
+
rake -s $@
|
58
|
+
|
59
|
+
gem-man:
|
60
|
+
$(MAKE) -C Documentation/ gem-man
|
61
|
+
tgz-man:
|
62
|
+
$(MAKE) -C Documentation/ install-man mandir=$(CURDIR)/man
|
63
|
+
.PHONY: tgz-man gem-man
|
64
|
+
|
65
|
+
.gem-manifest: .manifest
|
66
|
+
# (ls man/*.?; cat .manifest) | LC_ALL=C sort > $@+
|
67
|
+
LC_ALL=C sort < .manifest > $@+
|
68
|
+
cmp $@+ $@ || mv $@+ $@; rm -f $@+
|
69
|
+
.tgz-manifest: .manifest
|
70
|
+
LC_ALL=C sort < .manifest > $@+
|
71
|
+
cmp $@+ $@ || mv $@+ $@; rm -f $@+
|
72
|
+
.manifest: NEWS fix-perms
|
73
|
+
rm -rf man
|
74
|
+
(git ls-files; \
|
75
|
+
for i in $(pkg_extra); do echo $$i; done) | \
|
76
|
+
LC_ALL=C sort > $@+
|
77
|
+
cmp $@+ $@ || mv $@+ $@; rm -f $@+
|
78
|
+
$(pkgtgz): distdir = pkg/$(pkg)-$(VERSION)
|
79
|
+
$(pkgtgz): .tgz-manifest
|
80
|
+
@test -n "$(distdir)"
|
81
|
+
$(RM) -r $(distdir)
|
82
|
+
mkdir -p $(distdir)
|
83
|
+
tar cf - $$(cat .tgz-manifest) | (cd $(distdir) && tar xf -)
|
84
|
+
cd pkg && tar cf - $(pkg)-$(VERSION) | gzip -9 > $(@F)+
|
85
|
+
mv $@+ $@
|
86
|
+
|
87
|
+
package: $(pkgtgz) $(pkggem)
|
88
|
+
|
89
|
+
.PHONY: all .FORCE-GIT-VERSION-FILE test $(test_units) NEWS
|
90
|
+
.PHONY: check-warnings fix-perms
|
data/README
ADDED
@@ -0,0 +1,127 @@
|
|
1
|
+
yahns - sleepy, multi-threaded, non-blocking application server for Ruby
|
2
|
+
------------------------------------------------------------------------
|
3
|
+
|
4
|
+
A Free Software, multi-threaded, non-blocking network application server
|
5
|
+
designed for low _idle_ power consumption. It is primarily optimized
|
6
|
+
for applications with occasional users which see little or no traffic.
|
7
|
+
yahns currently hosts Rack/HTTP applications, but may eventually support
|
8
|
+
other application types. Unlike some existing servers, yahns is
|
9
|
+
extremely sensitive to fatal bugs in the applications it hosts.
|
10
|
+
|
11
|
+
Features
|
12
|
+
--------
|
13
|
+
|
14
|
+
* _zero_ wakeups when all clients are idle
|
15
|
+
* idle client connections may live forever if there is no FD pressure
|
16
|
+
* suitable for slow clients, fast clients, or a mixture of both
|
17
|
+
* HTTP/0.9 support
|
18
|
+
* HTTP/1.1 persistent connections and pipelining
|
19
|
+
* decodes HTTP chunked encoding for requests
|
20
|
+
* parses HTTP/1.1 trailers in requests
|
21
|
+
* supports streaming responses with lazy buffering for slow clients
|
22
|
+
* optional streaming input for fast clients
|
23
|
+
* able to host multiple applications with different settings
|
24
|
+
* uses epoll to scale to many idle connections
|
25
|
+
* abuses epoll as a load balancer between threads inside a process
|
26
|
+
* optional multi-process support (in addition to threads)
|
27
|
+
* fairly balances new clients between multiple processes (on Linux)
|
28
|
+
|
29
|
+
Supported Platforms
|
30
|
+
-------------------
|
31
|
+
|
32
|
+
yahns is developed primarily for modern GNU/Linux systems.
|
33
|
+
|
34
|
+
We may support kqueue for FreeBSD/OpenBSD/NetBSD if there is significant
|
35
|
+
interest. Non-Free systems/dependencies will never be supported
|
36
|
+
|
37
|
+
Supported Ruby implementations:
|
38
|
+
* (Matz) Ruby 2.0 or later
|
39
|
+
* Rubinius 2.0 or later (planned)
|
40
|
+
|
41
|
+
Contact
|
42
|
+
-------
|
43
|
+
|
44
|
+
We are happy to see feedback of all types via plain-text email.
|
45
|
+
Please send comments, user/dev discussion, patches, bug reports,
|
46
|
+
and pull requests to Eric Wong at: normalperson@yhbt.net
|
47
|
+
|
48
|
+
Public mailing list coming soon.
|
49
|
+
|
50
|
+
This README is our homepage, we would rather be working on HTTP servers
|
51
|
+
all day than worrying about the next browser vulnerability because
|
52
|
+
HTML/CSS/JS is too complicated for us.
|
53
|
+
|
54
|
+
* http://yahns.yhbt.net/README
|
55
|
+
|
56
|
+
Hacking
|
57
|
+
-------
|
58
|
+
|
59
|
+
We use git and follow the same development model as git itself
|
60
|
+
(mailing list-oriented, benevolent dictator).
|
61
|
+
|
62
|
+
git clone git://yahns.yhbt.net/yahns
|
63
|
+
|
64
|
+
Please use git-format-patch(1) and git-send-email(1) distributed with
|
65
|
+
the git(7) suite for generating and sending patches. Please format
|
66
|
+
pull requests with the git-request-pull(1) script (also distributed
|
67
|
+
with git(7)) and send them via email.
|
68
|
+
|
69
|
+
See http://www.git-scm.com/ for more information on git.
|
70
|
+
|
71
|
+
Design
|
72
|
+
------
|
73
|
+
|
74
|
+
yahns is designed to optimimally use multiple threads with non-blocking I/O.
|
75
|
+
The event loop is not a traditional single-threaded design with a mutex
|
76
|
+
slapped on as an afterthought, but designed from the beginning to utilize
|
77
|
+
multiple threads.
|
78
|
+
|
79
|
+
* two classes of long-lived, persistent threads
|
80
|
+
1. blocking acceptors
|
81
|
+
2. non-blocking event loop workers
|
82
|
+
* epoll acts as a queue (by using one-shot notifications)
|
83
|
+
* acceptors accept new clients and put them in the epoll "queue"
|
84
|
+
* workers pull clients off the queue, rearming them to epoll on EAGAIN
|
85
|
+
|
86
|
+
The end result is clients transition freely and fairly between threads
|
87
|
+
and will always be able to find the next idle thread to run on.
|
88
|
+
|
89
|
+
This design works with kqueue, too, and we will support kqueue if there
|
90
|
+
is interest. In fact, got our design inspiration from the name "kqueue"
|
91
|
+
when working on another project. We may also support libkqueue:
|
92
|
+
|
93
|
+
http://sourceforge.net/projects/libkqueue/
|
94
|
+
|
95
|
+
In addition to multiple threads, yahns optionally supports multiple
|
96
|
+
processes to work around low FD limits as well as contention in the:
|
97
|
+
|
98
|
+
* kernel (socket (de)allocation from accept/close)
|
99
|
+
* standard C library (malloc/free)
|
100
|
+
* Ruby VM (GVL, GC)
|
101
|
+
* application it hosts
|
102
|
+
|
103
|
+
Copyright
|
104
|
+
---------
|
105
|
+
|
106
|
+
Copyright 2013, Eric Wong <normalperson@yhbt.net> and all contributors.
|
107
|
+
License: GPLv3 or later <https://www.gnu.org/licenses/gpl-3.0.txt>
|
108
|
+
|
109
|
+
yahns is copyrighted Free Software by all contributors, see logs in
|
110
|
+
revision control for names and email addresses of all of them. yahns
|
111
|
+
contains code from Mongrel, unicorn, and Rainbows! which may also be
|
112
|
+
licensed under the GPLv2 or later.
|
113
|
+
|
114
|
+
yahns is free software; you can redistribute it and/or modify it
|
115
|
+
under the terms of the GNU General Public License as published by the
|
116
|
+
Free Software Foundation; either version 3 of the License, or (at your
|
117
|
+
option) any later version.
|
118
|
+
|
119
|
+
yahns is distributed in the hope that it will be useful, but WITHOUT ANY
|
120
|
+
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
121
|
+
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
122
|
+
for more details.
|
123
|
+
|
124
|
+
You should have received a copy of the GNU General Public License along
|
125
|
+
with this program; if not, see https://www.gnu.org/licenses/gpl-3.0.txt
|
126
|
+
|
127
|
+
lrg nabgure ubeevoyl-anzrq freire :>
|
data/Rakefile
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
# Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
|
2
|
+
# License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
|
3
|
+
require 'tempfile'
|
4
|
+
include Rake::DSL
|
5
|
+
task "NEWS" do
|
6
|
+
latest = nil
|
7
|
+
fp = Tempfile.new("NEWS", ".")
|
8
|
+
fp.sync = true
|
9
|
+
`git tag -l`.split(/\n/).reverse.each do |tag|
|
10
|
+
%r{\Av(.+)} =~ tag or next
|
11
|
+
version = $1
|
12
|
+
header, subject, body = `git cat-file tag #{tag}`.split(/\n\n/, 3)
|
13
|
+
header = header.split(/\n/)
|
14
|
+
tagger = header.grep(/\Atagger /)[0]
|
15
|
+
time = Time.at(tagger.split(/ /)[-2].to_i).utc
|
16
|
+
latest ||= time
|
17
|
+
date = time.strftime("%Y-%m-%d")
|
18
|
+
fp.puts "# #{version} / #{date}\n\n#{subject}"
|
19
|
+
if body && body.strip.size > 0
|
20
|
+
fp.puts "\n\n#{body}"
|
21
|
+
end
|
22
|
+
fp.puts
|
23
|
+
end
|
24
|
+
fp.write("Unreleased\n\n") unless fp.size > 0
|
25
|
+
fp.puts "# COPYRIGHT"
|
26
|
+
bdfl = 'Eric Wong <normalperson@yhbt.net>'
|
27
|
+
fp.puts "Copyright (C) 2013, #{bdfl} and all contributors"
|
28
|
+
fp.puts "License: GPLv3 or later (http://www.gnu.org/licenses/gpl-3.0.txt)"
|
29
|
+
fp.rewind
|
30
|
+
assert_equal fp.read, File.read("NEWS") rescue nil
|
31
|
+
fp.chmod 0644
|
32
|
+
File.rename(fp.path, "NEWS")
|
33
|
+
fp.close!
|
34
|
+
end
|
35
|
+
|
36
|
+
task rsync_docs: "NEWS" do
|
37
|
+
dest = ENV["RSYNC_DEST"] || "yahns.yhbt.net:/srv/yahns/"
|
38
|
+
top = %w(NEWS README COPYING)
|
39
|
+
files = []
|
40
|
+
|
41
|
+
# git-set-file-times is distributed with rsync,
|
42
|
+
# Also available at: http://yhbt.net/git-set-file-times
|
43
|
+
# on Debian systems: /usr/share/doc/rsync/scripts/git-set-file-times.gz
|
44
|
+
sh("git", "set-file-times", "examples", *top)
|
45
|
+
|
46
|
+
`git ls-files Documentation/*.txt`.split(/\n/).concat(top).each do |txt|
|
47
|
+
gz = "#{txt}.gz"
|
48
|
+
tmp = "#{gz}.#$$"
|
49
|
+
sh("gzip -9 < #{txt} > #{tmp}")
|
50
|
+
st = File.stat(txt)
|
51
|
+
File.utime(st.atime, st.mtime, tmp) # make nginx gzip_static happy
|
52
|
+
File.rename(tmp, gz)
|
53
|
+
files << txt
|
54
|
+
files << gz
|
55
|
+
end
|
56
|
+
sh("rsync --chmod=Fugo=r -av #{files.join(' ')} #{dest}")
|
57
|
+
|
58
|
+
examples = `git ls-files examples`.split("\n")
|
59
|
+
sh("rsync --chmod=Fugo=r -av #{examples.join(' ')} #{dest}/examples/")
|
60
|
+
end
|
data/bin/yahns
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
#!/this/will/be/overwritten/or/wrapped/anyways/do/not/worry/ruby
|
2
|
+
# -*- encoding: binary -*-
|
3
|
+
# Copyright (C) 2013, Eric Wong <normalperson@yhbt.net> and all contributors
|
4
|
+
# License: GPLv3 or later (https://www.gnu.org/licenses/gpl-3.0.txt)
|
5
|
+
$stdout.sync = $stderr.sync = true
|
6
|
+
require 'yahns'
|
7
|
+
require 'optparse'
|
8
|
+
config_file = daemonize = nil
|
9
|
+
OptionParser.new("", 24, " ") do |opts|
|
10
|
+
cmd = File.basename($0)
|
11
|
+
opts.banner = "Usage: #{cmd} [options]"
|
12
|
+
opts.separator "#{cmd} options:"
|
13
|
+
opts.on("-D", "--daemonize", "run daemonized in the background") do |d|
|
14
|
+
daemonize = !!d
|
15
|
+
end
|
16
|
+
opts.on("-c", "--config-file FILE", "yahns config file") do |f|
|
17
|
+
config_file = f
|
18
|
+
end
|
19
|
+
opts.separator "Common options:"
|
20
|
+
opts.on_tail("-h", "--help", "Show this message") do
|
21
|
+
puts opts.to_s
|
22
|
+
exit
|
23
|
+
end
|
24
|
+
opts.on_tail("-v", "--version", "Show version") do
|
25
|
+
puts "#{cmd} v#{Yahns::VERSION}"
|
26
|
+
exit
|
27
|
+
end
|
28
|
+
opts.parse!(ARGV)
|
29
|
+
end
|
30
|
+
server = Yahns::Server.new(Yahns::Config.new(config_file))
|
31
|
+
Yahns::Daemon.daemon(server) if daemonize
|
32
|
+
server.start.join
|
data/examples/README
ADDED
data/examples/init.sh
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
# To the extent possible under law, Eric Wong has waived all copyright and
|
3
|
+
# related or neighboring rights to this examples
|
4
|
+
set -e
|
5
|
+
# Example init script, this can be used with nginx, too,
|
6
|
+
# since nginx and yahns accept the same signals
|
7
|
+
|
8
|
+
# Feel free to change any of the following variables for your app:
|
9
|
+
TIMEOUT=${TIMEOUT-60}
|
10
|
+
APP_ROOT=/home/x/my_app/current
|
11
|
+
PID=$APP_ROOT/tmp/pids/yahns.pid
|
12
|
+
CMD="/usr/bin/yahns -D -c $APP_ROOT/config/yahns.rb"
|
13
|
+
INIT_CONF=$APP_ROOT/config/init.conf
|
14
|
+
action="$1"
|
15
|
+
set -u
|
16
|
+
|
17
|
+
test -f "$INIT_CONF" && . $INIT_CONF
|
18
|
+
|
19
|
+
old_pid="$PID.oldbin"
|
20
|
+
|
21
|
+
cd $APP_ROOT || exit 1
|
22
|
+
|
23
|
+
sig () {
|
24
|
+
test -s "$PID" && kill -$1 `cat $PID`
|
25
|
+
}
|
26
|
+
|
27
|
+
oldsig () {
|
28
|
+
test -s $old_pid && kill -$1 `cat $old_pid`
|
29
|
+
}
|
30
|
+
|
31
|
+
case $action in
|
32
|
+
start)
|
33
|
+
sig 0 && echo >&2 "Already running" && exit 0
|
34
|
+
$CMD
|
35
|
+
;;
|
36
|
+
stop)
|
37
|
+
sig QUIT && exit 0
|
38
|
+
echo >&2 "Not running"
|
39
|
+
;;
|
40
|
+
force-stop)
|
41
|
+
sig TERM && exit 0
|
42
|
+
echo >&2 "Not running"
|
43
|
+
;;
|
44
|
+
restart|reload)
|
45
|
+
sig HUP && echo reloaded OK && exit 0
|
46
|
+
echo >&2 "Couldn't reload, starting '$CMD' instead"
|
47
|
+
$CMD
|
48
|
+
;;
|
49
|
+
upgrade)
|
50
|
+
if sig USR2 && sleep 2 && sig 0 && oldsig QUIT
|
51
|
+
then
|
52
|
+
n=$TIMEOUT
|
53
|
+
while test -s $old_pid && test $n -ge 0
|
54
|
+
do
|
55
|
+
printf '.' && sleep 1 && n=$(( $n - 1 ))
|
56
|
+
done
|
57
|
+
echo
|
58
|
+
|
59
|
+
if test $n -lt 0 && test -s $old_pid
|
60
|
+
then
|
61
|
+
echo >&2 "$old_pid still exists after $TIMEOUT seconds"
|
62
|
+
exit 1
|
63
|
+
fi
|
64
|
+
exit 0
|
65
|
+
fi
|
66
|
+
echo >&2 "Couldn't upgrade, starting '$CMD' instead"
|
67
|
+
$CMD
|
68
|
+
;;
|
69
|
+
reopen-logs)
|
70
|
+
sig USR1
|
71
|
+
;;
|
72
|
+
*)
|
73
|
+
echo >&2 "Usage: $0 <start|stop|restart|upgrade|force-stop|reopen-logs>"
|
74
|
+
exit 1
|
75
|
+
;;
|
76
|
+
esac
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# To the extent possible under law, Eric Wong has waived all copyright and
|
2
|
+
# related or neighboring rights to this examples
|
3
|
+
#
|
4
|
+
# Multi-Processing-safe monkey patch for Logger
|
5
|
+
#
|
6
|
+
# This monkey patch fixes the case where "preload: true" is used and
|
7
|
+
# the application spawns a background thread upon being loaded.
|
8
|
+
#
|
9
|
+
# This removes all lock from the Logger code and solely relies on the
|
10
|
+
# underlying filesystem to handle write(2) system calls atomically when
|
11
|
+
# O_APPEND is used. This is safe in the presence of both multiple
|
12
|
+
# threads (native or green) and multiple processes when writing to
|
13
|
+
# a filesystem with POSIX O_APPEND semantics.
|
14
|
+
#
|
15
|
+
# It should be noted that the original locking on Logger could _never_ be
|
16
|
+
# considered reliable on non-POSIX filesystems with multiple processes,
|
17
|
+
# either, so nothing is lost in that case.
|
18
|
+
|
19
|
+
require 'logger'
|
20
|
+
class Logger::LogDevice
|
21
|
+
def write(message)
|
22
|
+
@dev.syswrite(message)
|
23
|
+
end
|
24
|
+
|
25
|
+
def close
|
26
|
+
@dev.close
|
27
|
+
end
|
28
|
+
end
|