unicorn 4.9.0 → 6.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.gitattributes +5 -0
- data/.olddoc.yml +13 -6
- data/Application_Timeouts +7 -7
- data/DESIGN +2 -4
- data/Documentation/.gitignore +1 -3
- data/Documentation/unicorn.1 +222 -0
- data/Documentation/unicorn_rails.1 +207 -0
- data/FAQ +17 -8
- data/GIT-VERSION-GEN +1 -1
- data/GNUmakefile +121 -56
- data/HACKING +1 -2
- data/ISSUES +40 -41
- data/KNOWN_ISSUES +11 -11
- data/LICENSE +2 -2
- data/Links +24 -25
- data/PHILOSOPHY +0 -6
- data/README +46 -39
- data/SIGNALS +2 -2
- data/Sandbox +10 -9
- data/TODO +0 -2
- data/TUNING +30 -9
- data/archive/slrnpull.conf +1 -1
- data/bin/unicorn +4 -2
- data/bin/unicorn_rails +3 -3
- data/examples/big_app_gc.rb +1 -1
- data/examples/init.sh +36 -8
- data/examples/logrotate.conf +17 -2
- data/examples/nginx.conf +14 -14
- data/examples/unicorn.conf.minimal.rb +2 -2
- data/examples/unicorn.conf.rb +3 -6
- data/examples/unicorn.socket +11 -0
- data/examples/unicorn@.service +40 -0
- data/ext/unicorn_http/common_field_optimization.h +23 -5
- data/ext/unicorn_http/ext_help.h +0 -20
- data/ext/unicorn_http/extconf.rb +37 -1
- data/ext/unicorn_http/global_variables.h +1 -1
- data/ext/unicorn_http/httpdate.c +2 -2
- data/ext/unicorn_http/unicorn_http.rl +167 -170
- data/ext/unicorn_http/unicorn_http_common.rl +1 -1
- data/lib/unicorn.rb +66 -46
- data/lib/unicorn/configurator.rb +110 -44
- data/lib/unicorn/const.rb +2 -25
- data/lib/unicorn/http_request.rb +110 -31
- data/lib/unicorn/http_response.rb +17 -31
- data/lib/unicorn/http_server.rb +238 -157
- data/lib/unicorn/launcher.rb +1 -1
- data/lib/unicorn/oob_gc.rb +6 -6
- data/lib/unicorn/socket_helper.rb +58 -78
- data/lib/unicorn/stream_input.rb +8 -7
- data/lib/unicorn/tee_input.rb +8 -10
- data/lib/unicorn/tmpio.rb +8 -7
- data/lib/unicorn/util.rb +5 -4
- data/lib/unicorn/worker.rb +36 -23
- data/t/GNUmakefile +3 -72
- data/t/README +4 -4
- data/t/t0011-active-unix-socket.sh +1 -1
- data/t/t0012-reload-empty-config.sh +2 -1
- data/t/t0301-no-default-middleware-ignored-in-config.sh +25 -0
- data/t/t0301.ru +13 -0
- data/t/test-lib.sh +2 -2
- data/test/benchmark/README +14 -4
- data/test/benchmark/ddstream.ru +50 -0
- data/test/benchmark/readinput.ru +40 -0
- data/test/benchmark/uconnect.perl +66 -0
- data/test/exec/test_exec.rb +73 -19
- data/test/test_helper.rb +40 -31
- data/test/unit/test_ccc.rb +91 -0
- data/test/unit/test_droplet.rb +1 -1
- data/test/unit/test_http_parser.rb +46 -16
- data/test/unit/test_http_parser_ng.rb +97 -114
- data/test/unit/test_request.rb +10 -10
- data/test/unit/test_response.rb +28 -16
- data/test/unit/test_server.rb +86 -12
- data/test/unit/test_signals.rb +8 -8
- data/test/unit/test_socket_helper.rb +14 -10
- data/test/unit/test_upload.rb +9 -14
- data/test/unit/test_util.rb +27 -2
- data/unicorn.gemspec +27 -19
- metadata +24 -45
- data/Documentation/GNUmakefile +0 -30
- data/Documentation/unicorn.1.txt +0 -185
- data/Documentation/unicorn_rails.1.txt +0 -175
- data/examples/git.ru +0 -13
- data/lib/unicorn/app/exec_cgi.rb +0 -154
- data/lib/unicorn/app/inetd.rb +0 -109
- data/lib/unicorn/ssl_client.rb +0 -11
- data/lib/unicorn/ssl_configurator.rb +0 -104
- data/lib/unicorn/ssl_server.rb +0 -42
- data/t/hijack.ru +0 -42
- data/t/t0016-trust-x-forwarded-false.sh +0 -30
- data/t/t0017-trust-x-forwarded-true.sh +0 -30
- data/t/t0200-rack-hijack.sh +0 -27
- data/test/unit/test_http_parser_xftrust.rb +0 -38
- data/test/unit/test_sni_hostnames.rb +0 -47
data/archive/slrnpull.conf
CHANGED
data/bin/unicorn
CHANGED
@@ -6,6 +6,7 @@
|
|
6
6
|
ENV["RACK_ENV"] ||= "development"
|
7
7
|
rackup_opts = Unicorn::Configurator::RACKUP
|
8
8
|
options = rackup_opts[:options]
|
9
|
+
set_no_default_middleware = true
|
9
10
|
|
10
11
|
op = OptionParser.new("", 24, ' ') do |opts|
|
11
12
|
cmd = File.basename($0)
|
@@ -29,7 +30,7 @@
|
|
29
30
|
|
30
31
|
opts.on("-I", "--include PATH",
|
31
32
|
"specify $LOAD_PATH (may be used more than once)") do |path|
|
32
|
-
$LOAD_PATH.unshift(*path.split(
|
33
|
+
$LOAD_PATH.unshift(*path.split(':'))
|
33
34
|
end
|
34
35
|
|
35
36
|
opts.on("-r", "--require LIBRARY",
|
@@ -60,7 +61,7 @@
|
|
60
61
|
|
61
62
|
opts.on("-N", "--no-default-middleware",
|
62
63
|
"do not load middleware implied by RACK_ENV") do |e|
|
63
|
-
rackup_opts[:no_default_middleware] = true
|
64
|
+
rackup_opts[:no_default_middleware] = true if set_no_default_middleware
|
64
65
|
end
|
65
66
|
|
66
67
|
opts.on("-D", "--daemonize", "run daemonized in the background") do |d|
|
@@ -110,6 +111,7 @@
|
|
110
111
|
opts.parse! ARGV
|
111
112
|
end
|
112
113
|
|
114
|
+
set_no_default_middleware = false
|
113
115
|
app = Unicorn.builder(ARGV[0] || 'config.ru', op)
|
114
116
|
op = nil
|
115
117
|
|
data/bin/unicorn_rails
CHANGED
@@ -30,7 +30,7 @@
|
|
30
30
|
|
31
31
|
opts.on("-I", "--include PATH",
|
32
32
|
"specify $LOAD_PATH (may be used more than once)") do |path|
|
33
|
-
$LOAD_PATH.unshift(*path.split(
|
33
|
+
$LOAD_PATH.unshift(*path.split(':'))
|
34
34
|
end
|
35
35
|
|
36
36
|
opts.on("-r", "--require LIBRARY",
|
@@ -132,11 +132,11 @@ def rails_builder(ru, op, daemonize)
|
|
132
132
|
|
133
133
|
# this lambda won't run until after forking if preload_app is false
|
134
134
|
# this runs after config file reloading
|
135
|
-
lambda do
|
135
|
+
lambda do |x, server|
|
136
136
|
# Rails 3 includes a config.ru, use it if we find it after
|
137
137
|
# working_directory is bound.
|
138
138
|
::File.exist?('config.ru') and
|
139
|
-
return Unicorn.builder('config.ru', op).call
|
139
|
+
return Unicorn.builder('config.ru', op).call(x, server)
|
140
140
|
|
141
141
|
# Load Rails and (possibly) the private version of Rack it bundles.
|
142
142
|
begin
|
data/examples/big_app_gc.rb
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
# see {Unicorn::OobGC}[
|
1
|
+
# see {Unicorn::OobGC}[https://yhbt.net/unicorn/Unicorn/OobGC.html]
|
2
2
|
# Unicorn::OobGC was broken in Unicorn v3.3.1 - v3.6.1 and fixed in v3.6.2
|
data/examples/init.sh
CHANGED
@@ -1,7 +1,16 @@
|
|
1
1
|
#!/bin/sh
|
2
2
|
set -e
|
3
|
+
### BEGIN INIT INFO
|
4
|
+
# Provides: unicorn
|
5
|
+
# Required-Start: $local_fs $network
|
6
|
+
# Required-Stop: $local_fs $network
|
7
|
+
# Default-Start: 2 3 4 5
|
8
|
+
# Default-Stop: 0 1 6
|
9
|
+
# Short-Description: Start/stop unicorn Rack app server
|
10
|
+
### END INIT INFO
|
11
|
+
|
3
12
|
# Example init script, this can be used with nginx, too,
|
4
|
-
# since nginx and unicorn accept the same signals
|
13
|
+
# since nginx and unicorn accept the same signals.
|
5
14
|
|
6
15
|
# Feel free to change any of the following variables for your app:
|
7
16
|
TIMEOUT=${TIMEOUT-60}
|
@@ -9,21 +18,22 @@ APP_ROOT=/home/x/my_app/current
|
|
9
18
|
PID=$APP_ROOT/tmp/pids/unicorn.pid
|
10
19
|
CMD="/usr/bin/unicorn -D -c $APP_ROOT/config/unicorn.rb"
|
11
20
|
INIT_CONF=$APP_ROOT/config/init.conf
|
21
|
+
UPGRADE_DELAY=${UPGRADE_DELAY-2}
|
12
22
|
action="$1"
|
13
23
|
set -u
|
14
24
|
|
15
25
|
test -f "$INIT_CONF" && . $INIT_CONF
|
16
26
|
|
17
|
-
|
27
|
+
OLD="$PID.oldbin"
|
18
28
|
|
19
29
|
cd $APP_ROOT || exit 1
|
20
30
|
|
21
31
|
sig () {
|
22
|
-
test -s "$PID" && kill -$1
|
32
|
+
test -s "$PID" && kill -$1 $(cat $PID)
|
23
33
|
}
|
24
34
|
|
25
35
|
oldsig () {
|
26
|
-
test -s $
|
36
|
+
test -s "$OLD" && kill -$1 $(cat $OLD)
|
27
37
|
}
|
28
38
|
|
29
39
|
case $action in
|
@@ -45,18 +55,36 @@ restart|reload)
|
|
45
55
|
$CMD
|
46
56
|
;;
|
47
57
|
upgrade)
|
48
|
-
if
|
58
|
+
if oldsig 0
|
59
|
+
then
|
60
|
+
echo >&2 "Old upgraded process still running with $OLD"
|
61
|
+
exit 1
|
62
|
+
fi
|
63
|
+
|
64
|
+
cur_pid=
|
65
|
+
if test -s "$PID"
|
66
|
+
then
|
67
|
+
cur_pid=$(cat $PID)
|
68
|
+
fi
|
69
|
+
|
70
|
+
if test -n "$cur_pid" &&
|
71
|
+
kill -USR2 "$cur_pid" &&
|
72
|
+
sleep $UPGRADE_DELAY &&
|
73
|
+
new_pid=$(cat $PID) &&
|
74
|
+
test x"$new_pid" != x"$cur_pid" &&
|
75
|
+
kill -0 "$new_pid" &&
|
76
|
+
kill -QUIT "$cur_pid"
|
49
77
|
then
|
50
78
|
n=$TIMEOUT
|
51
|
-
while
|
79
|
+
while kill -0 "$cur_pid" 2>/dev/null && test $n -ge 0
|
52
80
|
do
|
53
81
|
printf '.' && sleep 1 && n=$(( $n - 1 ))
|
54
82
|
done
|
55
83
|
echo
|
56
84
|
|
57
|
-
if test $n -lt 0 &&
|
85
|
+
if test $n -lt 0 && kill -0 "$cur_pid" 2>/dev/null
|
58
86
|
then
|
59
|
-
echo >&2 "$
|
87
|
+
echo >&2 "$cur_pid still running after $TIMEOUT seconds"
|
60
88
|
exit 1
|
61
89
|
fi
|
62
90
|
exit 0
|
data/examples/logrotate.conf
CHANGED
@@ -2,7 +2,10 @@
|
|
2
2
|
# /etc/logrotate.d/unicorn_app on my Debian systems
|
3
3
|
#
|
4
4
|
# See the logrotate(8) manpage for more information:
|
5
|
-
#
|
5
|
+
# https://linux.die.net/man/8/logrotate
|
6
|
+
#
|
7
|
+
# public logrotate-related discussion in our archives:
|
8
|
+
# https://yhbt.net/unicorn-public/?q=logrotate
|
6
9
|
|
7
10
|
# Modify the following glob to match the logfiles your app writes to:
|
8
11
|
/var/log/unicorn_app/*.log {
|
@@ -22,7 +25,19 @@
|
|
22
25
|
# config. Unicorn supports the USR1 signal and we send it
|
23
26
|
# as our "lastaction" action:
|
24
27
|
lastaction
|
25
|
-
#
|
28
|
+
# For systemd users, assuming you use two services
|
29
|
+
# (as recommended) to allow zero-downtime upgrades.
|
30
|
+
# Only one service needs to be started, but signaling
|
31
|
+
# both here is harmless as long as they're both enabled
|
32
|
+
systemctl kill -s SIGUSR1 unicorn@1.service
|
33
|
+
systemctl kill -s SIGUSR1 unicorn@2.service
|
34
|
+
|
35
|
+
# Examples for other process management systems appreciated
|
36
|
+
# Mail us at unicorn-public@yhbt.net
|
37
|
+
# (see above for archives)
|
38
|
+
|
39
|
+
# If you use a pid file and assuming your pid file
|
40
|
+
# is in /var/run/unicorn_app/pid
|
26
41
|
pid=/var/run/unicorn_app/pid
|
27
42
|
test -s $pid && kill -USR1 "$(cat $pid)"
|
28
43
|
endscript
|
data/examples/nginx.conf
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# This is example contains the bare mininum to get nginx going with
|
2
|
-
#
|
2
|
+
# unicorn servers. Generally these configuration settings
|
3
3
|
# are applicable to other HTTP application servers (and not just Ruby
|
4
4
|
# ones), so if you have one working well for proxying another app
|
5
5
|
# server, feel free to continue using it.
|
@@ -44,8 +44,8 @@ http {
|
|
44
44
|
# click tracking!
|
45
45
|
access_log /path/to/nginx.access.log combined;
|
46
46
|
|
47
|
-
# you generally want to serve static files with nginx since
|
48
|
-
#
|
47
|
+
# you generally want to serve static files with nginx since
|
48
|
+
# unicorn is not and will never be optimized for it
|
49
49
|
sendfile on;
|
50
50
|
|
51
51
|
tcp_nopush on; # off may be better for *some* Comet/long-poll stuff
|
@@ -56,7 +56,8 @@ http {
|
|
56
56
|
# to configure it all in one place here for static files and also
|
57
57
|
# to disable gzip for clients who don't get gzip/deflate right.
|
58
58
|
# There are other gzip settings that may be needed used to deal with
|
59
|
-
# bad clients out there, see
|
59
|
+
# bad clients out there, see
|
60
|
+
# https://nginx.org/en/docs/http/ngx_http_gzip_module.html
|
60
61
|
gzip on;
|
61
62
|
gzip_http_version 1.0;
|
62
63
|
gzip_proxied any;
|
@@ -67,10 +68,10 @@ http {
|
|
67
68
|
text/javascript application/x-javascript
|
68
69
|
application/atom+xml;
|
69
70
|
|
70
|
-
# this can be any application server, not just
|
71
|
+
# this can be any application server, not just unicorn
|
71
72
|
upstream app_server {
|
72
73
|
# fail_timeout=0 means we always retry an upstream even if it failed
|
73
|
-
# to return a good HTTP response (in case the
|
74
|
+
# to return a good HTTP response (in case the unicorn master nukes a
|
74
75
|
# single worker for timing out).
|
75
76
|
|
76
77
|
# for UNIX domain socket setups:
|
@@ -112,12 +113,12 @@ http {
|
|
112
113
|
# try_files directive appeared in in nginx 0.7.27 and has stabilized
|
113
114
|
# over time. Older versions of nginx (e.g. 0.6.x) requires
|
114
115
|
# "if (!-f $request_filename)" which was less efficient:
|
115
|
-
#
|
116
|
+
# https://yhbt.net/unicorn.git/tree/examples/nginx.conf?id=v3.3.1#n127
|
116
117
|
try_files $uri/index.html $uri.html $uri @app;
|
117
118
|
|
118
119
|
location @app {
|
119
120
|
# an HTTP header important enough to have its own Wikipedia entry:
|
120
|
-
#
|
121
|
+
# https://en.wikipedia.org/wiki/X-Forwarded-For
|
121
122
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
122
123
|
|
123
124
|
# enable this if you forward HTTPS traffic to unicorn,
|
@@ -132,12 +133,11 @@ http {
|
|
132
133
|
# redirects, we set the Host: header above already.
|
133
134
|
proxy_redirect off;
|
134
135
|
|
135
|
-
# set
|
136
|
-
#
|
137
|
-
#
|
138
|
-
#
|
139
|
-
#
|
140
|
-
# client can become a bottleneck of Unicorn.
|
136
|
+
# It's also safe to set if you're using only serving fast clients
|
137
|
+
# with unicorn + nginx, but not slow clients. You normally want
|
138
|
+
# nginx to buffer responses to slow clients, even with Rails 3.1
|
139
|
+
# streaming because otherwise a slow client can become a bottleneck
|
140
|
+
# of unicorn.
|
141
141
|
#
|
142
142
|
# The Rack application may also set "X-Accel-Buffering (yes|no)"
|
143
143
|
# in the response headers do disable/enable buffering on a
|
@@ -1,9 +1,9 @@
|
|
1
1
|
# Minimal sample configuration file for Unicorn (not Rack) when used
|
2
2
|
# with daemonization (unicorn -D) started in your working directory.
|
3
3
|
#
|
4
|
-
# See
|
4
|
+
# See https://yhbt.net/unicorn/Unicorn/Configurator.html for complete
|
5
5
|
# documentation.
|
6
|
-
# See also
|
6
|
+
# See also https://yhbt.net/unicorn/examples/unicorn.conf.rb for
|
7
7
|
# a more verbose configuration using more features.
|
8
8
|
|
9
9
|
listen 2007 # by default Unicorn listens on port 8080
|
data/examples/unicorn.conf.rb
CHANGED
@@ -2,10 +2,10 @@
|
|
2
2
|
#
|
3
3
|
# This configuration file documents many features of Unicorn
|
4
4
|
# that may not be needed for some applications. See
|
5
|
-
#
|
5
|
+
# https://yhbt.net/unicorn/examples/unicorn.conf.minimal.rb
|
6
6
|
# for a much simpler configuration file.
|
7
7
|
#
|
8
|
-
# See
|
8
|
+
# See https://yhbt.net/unicorn/Unicorn/Configurator.html for complete
|
9
9
|
# documentation.
|
10
10
|
|
11
11
|
# Use at least one worker per core if you're on a dedicated server,
|
@@ -40,11 +40,8 @@
|
|
40
40
|
stderr_path "/path/to/app/shared/log/unicorn.stderr.log"
|
41
41
|
stdout_path "/path/to/app/shared/log/unicorn.stdout.log"
|
42
42
|
|
43
|
-
# combine Ruby 2.0.
|
44
|
-
# http://rubyenterpriseedition.com/faq.html#adapt_apps_for_cow
|
43
|
+
# combine Ruby 2.0.0+ with "preload_app true" for memory savings
|
45
44
|
preload_app true
|
46
|
-
GC.respond_to?(:copy_on_write_friendly=) and
|
47
|
-
GC.copy_on_write_friendly = true
|
48
45
|
|
49
46
|
# Enable this flag to have unicorn test client connections by writing the
|
50
47
|
# beginning of the HTTP headers before calling the application. This
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# ==> /etc/systemd/system/unicorn@.service <==
|
2
|
+
# Since SIGUSR2 upgrades do not work under systemd, this service file
|
3
|
+
# allows starting two simultaneous services during upgrade time
|
4
|
+
# (e.g. unicorn@1 unicorn@2) with the intention that they take
|
5
|
+
# turns running in-between upgrades. This should allow upgrading
|
6
|
+
# without downtime.
|
7
|
+
|
8
|
+
[Unit]
|
9
|
+
Description = unicorn Rack application server %i
|
10
|
+
Wants = unicorn.socket
|
11
|
+
After = unicorn.socket
|
12
|
+
|
13
|
+
[Service]
|
14
|
+
# bundler users must use the "--keep-file-descriptors" switch, here:
|
15
|
+
# ExecStart = bundle exec --keep-file-descriptors unicorn -c ...
|
16
|
+
ExecStart = /usr/bin/unicorn -c /path/to/unicorn.conf.rb /path/to/config.ru
|
17
|
+
|
18
|
+
# NonBlocking MUST be true if using socket activation with unicorn.
|
19
|
+
# Otherwise, there's a small window in-between when the non-blocking
|
20
|
+
# flag is set by us and our accept4 call where systemd can momentarily
|
21
|
+
# make the socket blocking, causing us to block on accept4:
|
22
|
+
NonBlocking = true
|
23
|
+
Sockets = unicorn.socket
|
24
|
+
|
25
|
+
KillSignal = SIGQUIT
|
26
|
+
User = nobody
|
27
|
+
Group = nogroup
|
28
|
+
ExecReload = /bin/kill -HUP $MAINPID
|
29
|
+
|
30
|
+
# This is based on the Unicorn::Configurator#timeout directive,
|
31
|
+
# adding a few seconds for scheduling differences:
|
32
|
+
TimeoutStopSec = 62
|
33
|
+
|
34
|
+
# Only kill the master process, it may be harmful to signal
|
35
|
+
# workers via default "control-group" setting since some
|
36
|
+
# Ruby extensions and applications misbehave on interrupts
|
37
|
+
KillMode = process
|
38
|
+
|
39
|
+
[Install]
|
40
|
+
WantedBy = multi-user.target
|
@@ -58,6 +58,23 @@ static struct common_field common_http_fields[] = {
|
|
58
58
|
|
59
59
|
#define HTTP_PREFIX "HTTP_"
|
60
60
|
#define HTTP_PREFIX_LEN (sizeof(HTTP_PREFIX) - 1)
|
61
|
+
static ID id_uminus;
|
62
|
+
|
63
|
+
/* this dedupes under Ruby 2.5+ (December 2017) */
|
64
|
+
static VALUE str_dd_freeze(VALUE str)
|
65
|
+
{
|
66
|
+
if (STR_UMINUS_DEDUPE)
|
67
|
+
return rb_funcall(str, id_uminus, 0);
|
68
|
+
|
69
|
+
/* freeze,since it speeds up older MRI slightly */
|
70
|
+
OBJ_FREEZE(str);
|
71
|
+
return str;
|
72
|
+
}
|
73
|
+
|
74
|
+
static VALUE str_new_dd_freeze(const char *ptr, long len)
|
75
|
+
{
|
76
|
+
return str_dd_freeze(rb_str_new(ptr, len));
|
77
|
+
}
|
61
78
|
|
62
79
|
/* this function is not performance-critical, called only at load time */
|
63
80
|
static void init_common_fields(void)
|
@@ -65,19 +82,20 @@ static void init_common_fields(void)
|
|
65
82
|
int i;
|
66
83
|
struct common_field *cf = common_http_fields;
|
67
84
|
char tmp[64];
|
85
|
+
|
86
|
+
id_uminus = rb_intern("-@");
|
68
87
|
memcpy(tmp, HTTP_PREFIX, HTTP_PREFIX_LEN);
|
69
88
|
|
70
89
|
for(i = ARRAY_SIZE(common_http_fields); --i >= 0; cf++) {
|
71
90
|
/* Rack doesn't like certain headers prefixed with "HTTP_" */
|
72
91
|
if (!strcmp("CONTENT_LENGTH", cf->name) ||
|
73
92
|
!strcmp("CONTENT_TYPE", cf->name)) {
|
74
|
-
cf->value =
|
93
|
+
cf->value = str_new_dd_freeze(cf->name, cf->len);
|
75
94
|
} else {
|
76
95
|
memcpy(tmp + HTTP_PREFIX_LEN, cf->name, cf->len + 1);
|
77
|
-
cf->value =
|
96
|
+
cf->value = str_new_dd_freeze(tmp, HTTP_PREFIX_LEN + cf->len);
|
78
97
|
}
|
79
|
-
|
80
|
-
rb_global_variable(&cf->value);
|
98
|
+
rb_gc_register_mark_object(cf->value);
|
81
99
|
}
|
82
100
|
}
|
83
101
|
|
@@ -105,7 +123,7 @@ static VALUE uncommon_field(const char *field, size_t flen)
|
|
105
123
|
memcpy(RSTRING_PTR(f) + HTTP_PREFIX_LEN, field, flen);
|
106
124
|
assert(*(RSTRING_PTR(f) + RSTRING_LEN(f)) == '\0' &&
|
107
125
|
"string didn't end with \\0"); /* paranoia */
|
108
|
-
return
|
126
|
+
return HASH_ASET_DEDUPE ? f : str_dd_freeze(f);
|
109
127
|
}
|
110
128
|
|
111
129
|
#endif /* common_field_optimization_h */
|
data/ext/unicorn_http/ext_help.h
CHANGED
@@ -1,26 +1,6 @@
|
|
1
1
|
#ifndef ext_help_h
|
2
2
|
#define ext_help_h
|
3
3
|
|
4
|
-
#ifndef RSTRING_PTR
|
5
|
-
#define RSTRING_PTR(s) (RSTRING(s)->ptr)
|
6
|
-
#endif /* !defined(RSTRING_PTR) */
|
7
|
-
#ifndef RSTRING_LEN
|
8
|
-
#define RSTRING_LEN(s) (RSTRING(s)->len)
|
9
|
-
#endif /* !defined(RSTRING_LEN) */
|
10
|
-
|
11
|
-
#ifndef HAVE_RB_STR_SET_LEN
|
12
|
-
# ifdef RUBINIUS
|
13
|
-
# error we should never get here with current Rubinius (1.x)
|
14
|
-
# endif
|
15
|
-
/* this is taken from Ruby 1.8.7, 1.8.6 may not have it */
|
16
|
-
static void rb_18_str_set_len(VALUE str, long len)
|
17
|
-
{
|
18
|
-
RSTRING(str)->len = len;
|
19
|
-
RSTRING(str)->ptr[len] = '\0';
|
20
|
-
}
|
21
|
-
# define rb_str_set_len(str,len) rb_18_str_set_len(str,len)
|
22
|
-
#endif /* !defined(HAVE_RB_STR_SET_LEN) */
|
23
|
-
|
24
4
|
/* not all Ruby implementations support frozen objects (Rubinius does not) */
|
25
5
|
#if defined(OBJ_FROZEN)
|
26
6
|
# define assert_frozen(f) assert(OBJ_FROZEN(f) && "unfrozen object")
|
data/ext/unicorn_http/extconf.rb
CHANGED
@@ -1,10 +1,46 @@
|
|
1
1
|
# -*- encoding: binary -*-
|
2
2
|
require 'mkmf'
|
3
3
|
|
4
|
+
unless RUBY_VERSION < '3.1'
|
5
|
+
warn "Unicorn was only tested against MRI up to 3.0.\n" \
|
6
|
+
"It might not properly work with #{RUBY_VERSION}"
|
7
|
+
end
|
8
|
+
|
4
9
|
have_macro("SIZEOF_OFF_T", "ruby.h") or check_sizeof("off_t", "sys/types.h")
|
5
10
|
have_macro("SIZEOF_SIZE_T", "ruby.h") or check_sizeof("size_t", "sys/types.h")
|
6
11
|
have_macro("SIZEOF_LONG", "ruby.h") or check_sizeof("long", "sys/types.h")
|
7
|
-
have_func("rb_str_set_len", "ruby.h")
|
12
|
+
have_func("rb_str_set_len", "ruby.h") or abort 'Ruby 1.9.3+ required'
|
13
|
+
have_func("rb_hash_clear", "ruby.h") # Ruby 2.0+
|
8
14
|
have_func("gmtime_r", "time.h")
|
9
15
|
|
16
|
+
message('checking if String#-@ (str_uminus) dedupes... ')
|
17
|
+
begin
|
18
|
+
a = -(%w(t e s t).join)
|
19
|
+
b = -(%w(t e s t).join)
|
20
|
+
if a.equal?(b)
|
21
|
+
$CPPFLAGS += ' -DSTR_UMINUS_DEDUPE=1 '
|
22
|
+
message("yes\n")
|
23
|
+
else
|
24
|
+
$CPPFLAGS += ' -DSTR_UMINUS_DEDUPE=0 '
|
25
|
+
message("no, needs Ruby 2.5+\n")
|
26
|
+
end
|
27
|
+
rescue NoMethodError
|
28
|
+
$CPPFLAGS += ' -DSTR_UMINUS_DEDUPE=0 '
|
29
|
+
message("no, String#-@ not available\n")
|
30
|
+
end
|
31
|
+
|
32
|
+
message('checking if Hash#[]= (rb_hash_aset) dedupes... ')
|
33
|
+
h = {}
|
34
|
+
x = {}
|
35
|
+
r = rand.to_s
|
36
|
+
h[%W(#{r}).join('')] = :foo
|
37
|
+
x[%W(#{r}).join('')] = :foo
|
38
|
+
if x.keys[0].equal?(h.keys[0])
|
39
|
+
$CPPFLAGS += ' -DHASH_ASET_DEDUPE=1 '
|
40
|
+
message("yes\n")
|
41
|
+
else
|
42
|
+
$CPPFLAGS += ' -DHASH_ASET_DEDUPE=0 '
|
43
|
+
message("no, needs Ruby 2.6+\n")
|
44
|
+
end
|
45
|
+
|
10
46
|
create_makefile("unicorn_http")
|