rainbows 5.0.0.5.ge717 → 5.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ca864460733b7f19467c85350948190f34dd8063
4
- data.tar.gz: bddf103c8b19c4d936e1ff67a939dfe60b63ecf6
3
+ metadata.gz: b8cc2123c4d83730d582b5f321357fd6137ef00c
4
+ data.tar.gz: 10d4985653c1dd1d67a69e4947da5ea53044b08c
5
5
  SHA512:
6
- metadata.gz: c4db9d819af7d582d7dc5eb9b714ea818e5e7d2832073b9a3c60f9c829729acb032b242b9b5939fd5269a511ca4347455510c7ee0ed3a07f69cbf37cc0d8a563
7
- data.tar.gz: fb42bee73a9ac1c9893c1866457fd6f4d7570c8cdb62399745588b948feb0b9892c9a9e3c09f4c25f9aa4a2f783382b5813be0d1d58f4cab56a114bca5c4c348
6
+ metadata.gz: 274906c5e42e82a6ee566776a8a9a2c488cf9c1dca38a415a35355062b02b156bedbe1c617b36bce4264a28ed5cc166867ccb9a3403a61172ef639eab5de06b1
7
+ data.tar.gz: 16f81b05cdf620fe65ffe76dd266132e89856ccbf45c6f9748e75f2dc45e8e03afc3e586edfc01fbd6ded9d794348b06c5c71126f5dd38e003c6161e77bcd1f1
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
- DEF_VER = "v5.0.0"
2
+ DEF_VER = "v5.1.0"
3
3
  CONSTANT = "Rainbows::Const::RAINBOWS_VERSION"
4
4
  RVF = "lib/rainbows/version.rb"
5
5
  GVF = "GIT-VERSION-FILE"
data/README CHANGED
@@ -159,6 +159,15 @@ don't email the git mailing list or maintainer with \Rainbows! patches.
159
159
  There is NO WARRANTY whatsoever if anything goes wrong, but let us know
160
160
  and we'll try our best to fix it.
161
161
 
162
+ Rainbows! is extremely sensitive to fatal bugs in the apps it hosts.
163
+ Each Rainbows! worker process may be handling thousands of clients;
164
+ unexpectedly killing the process will abort _all_ of those
165
+ connections. Lives may be lost!
166
+
167
+ Rainbows! hackers are not responsible for your application/library bugs.
168
+ Use an application server which is tolerant of buggy applications
169
+ if you cannot be bothered to fix all your fatal bugs.
170
+
162
171
  == Contact
163
172
 
164
173
  All feedback (bug reports, user/development discussion, patches, pull
data/SIGNALS CHANGED
@@ -24,9 +24,9 @@ between \Rainbows!, unicorn and nginx.
24
24
  * INT/TERM - quick shutdown, kills all workers immediately
25
25
 
26
26
  * QUIT - graceful shutdown, waits for workers to finish their
27
- current request before finishing. This currently does not
28
- wait for requests deferred to a separate thread when using
29
- EventMachine (when app.deferred?(env) => true)
27
+ current request before finishing. Since Rainbows 5.1.0 (Jan 2017),
28
+ this waits requests deferred to a separate thread with
29
+ EventMachine (app.deferred?(env) => true).
30
30
 
31
31
  * USR1 - reopen all logs owned by the master and all workers
32
32
  See Unicorn::Util.reopen_logs for what is considered a log.
@@ -6,6 +6,11 @@
6
6
  # block, otherwise Unicorn::Configurator directives may be used anywhere
7
7
  # in the file.
8
8
  #
9
+ # Warning: The "timeout" directive in unicorn is far more dangerous
10
+ # in Rainbows!, since ALL requests running on a process will be lost
11
+ # on worker death, not just one. Instead, handle application-level
12
+ # timeouts yourself: https://bogomips.org/unicorn/Application_Timeouts.html
13
+ #
9
14
  # Rainbows! do
10
15
  # use :ThreadSpawn # concurrency model to use
11
16
  # worker_connections 400
@@ -65,6 +65,11 @@ def em_client_class
65
65
  end
66
66
  end
67
67
 
68
+ def defers_finished?
69
+ # EventMachine 1.0.0+ has defers_finished?
70
+ EM.respond_to?(:defers_finished?) ? EM.defers_finished? : true
71
+ end
72
+
68
73
  # runs inside each forked worker, this sits around and waits
69
74
  # for connections and doesn't die until the parent dies (or is
70
75
  # given a INT, QUIT, or TERM signal)
@@ -101,7 +106,10 @@ def worker_loop(worker) # :nodoc:
101
106
  end
102
107
  end
103
108
  EM.add_periodic_timer(1) do
104
- EM.stop if ! Rainbows.tick && conns.empty? && EM.reactor_running?
109
+ if ! Rainbows.tick && conns.empty? && defers_finished? &&
110
+ EM.reactor_running?
111
+ EM.stop
112
+ end
105
113
  end
106
114
  LISTENERS.map! do |s|
107
115
  EM.watch(s, Rainbows::EventMachine::Server) do |c|
@@ -41,6 +41,7 @@ ifeq ($(RUBY_ENGINE),ruby)
41
41
  endif
42
42
  models += FiberSpawn
43
43
  models += FiberPool
44
+ models += EventMachine
44
45
 
45
46
  RUBY_LE_2_1 := $(shell $(RUBY) -e 'puts(RUBY_VERSION.to_f <= 2.1)')
46
47
  ifeq ($(RUBY_LE_2_1), true)
@@ -48,7 +49,6 @@ ifeq ($(RUBY_ENGINE),ruby)
48
49
  models += CoolioThreadPool
49
50
  models += CoolioThreadSpawn
50
51
  models += CoolioFiberSpawn
51
- models += EventMachine
52
52
  models += NeverBlock
53
53
  endif
54
54
  endif
@@ -6,12 +6,18 @@
6
6
 
7
7
  class DeferredApp < Struct.new(:app)
8
8
  def deferred?(env)
9
- env["PATH_INFO"] == "/deferred"
9
+ env["PATH_INFO"] =~ %r{\A/deferred}
10
10
  end
11
11
 
12
12
  def call(env)
13
13
  env["rack.multithread"] or raise RuntimeError, "rack.multithread not true"
14
14
  body = "#{Thread.current.inspect}\n"
15
+ if env["PATH_INFO"] =~ %r{\A/deferred(\d+)}
16
+ delay = $1.to_i
17
+ File.open(ENV['fifo'], 'w') { |fp| fp.write "sleeping #{delay}s\n" }
18
+ body = "deferred sleep\n"
19
+ sleep(delay)
20
+ end
15
21
  headers = {
16
22
  "Content-Type" => "text/plain",
17
23
  "Content-Length" => body.size.to_s,
@@ -0,0 +1,121 @@
1
+ #!/bin/sh
2
+ . ./test-lib.sh
3
+ STRACE=$(which strace 2>/dev/null || :)
4
+ if ! test -x "$STRACE"
5
+ then
6
+ t_info "strace not found, skipping $T"
7
+ exit 0
8
+ fi
9
+ if test x"$(uname -s)" != xLinux
10
+ then
11
+ t_info "Linux is the only supported OS for $T"
12
+ exit 0
13
+ fi
14
+
15
+ # these buffer internally in external libraries, so we can't detect when
16
+ # to use TCP_CORK
17
+ skip_models EventMachine NeverBlock
18
+ skip_models StreamResponseEpoll
19
+ skip_models Coolio CoolioThreadPool CoolioThreadSpawn
20
+ skip_models Revactor Rev RevThreadPool RevThreadSpawn
21
+
22
+ # not sure why, but we don't have time to care about Ruby 1.8 too much
23
+ case $RUBY_VERSION in
24
+ 1.8.*) skip_models WriterThreadSpawn WriterThreadPool ;;
25
+ esac
26
+
27
+ t_plan 13 "Kgio autopush tests"
28
+
29
+ start_strace () {
30
+ # dbgcat strace_out
31
+ > $strace_out
32
+ sleep 1
33
+ strace -p $worker_pid -e '!futex' -f -o $strace_out &
34
+ strace_pid=$!
35
+ while ! test -s $strace_out; do sleep 1; done
36
+ }
37
+
38
+ check_TCP_CORK () {
39
+ nr=0
40
+ while test 2 -gt $(grep TCP_CORK $strace_out | count_lines)
41
+ do
42
+ nr=$(( $nr + 1 ))
43
+ if test $nr -gt 30
44
+ then
45
+ dbgcat strace_out
46
+ die "waited too long ($nr seconds) for TCP_CORK"
47
+ fi
48
+ sleep 1
49
+ done
50
+
51
+ test 2 -eq $(grep TCP_CORK $strace_out | count_lines)
52
+ fgrep 'SOL_TCP, TCP_CORK, [0],' $strace_out
53
+ fgrep 'SOL_TCP, TCP_CORK, [1],' $strace_out
54
+ }
55
+
56
+ t_begin "setup and start" && {
57
+ rainbows_setup $model 1 1
58
+ rtmpfiles strace_out
59
+ ed -s $unicorn_config <<EOF
60
+ ,s/^listen.*/listen "$listen", :tcp_nodelay => true, :tcp_nopush => true/
61
+ w
62
+ EOF
63
+ rainbows -D large-file-response.ru -c $unicorn_config -E none
64
+ rainbows_wait_start
65
+ }
66
+
67
+ t_begin "read worker pid" && {
68
+ worker_pid=$(curl -sSf http://$listen/pid)
69
+ kill -0 $worker_pid
70
+ }
71
+
72
+ t_begin "start strace on worker" && start_strace
73
+
74
+ t_begin "reading RSS uncorks" && {
75
+ curl -sSf http://$listen/rss >/dev/null
76
+ }
77
+
78
+ t_begin "restart strace on worker" && {
79
+ kill $strace_pid
80
+ wait
81
+ start_strace
82
+ }
83
+
84
+ t_begin "reading static file uncorks" && {
85
+ curl -sSf http://$listen/random_blob >/dev/null
86
+ check_TCP_CORK
87
+ }
88
+
89
+ t_begin "stop strace on worker" && {
90
+ kill $strace_pid
91
+ wait
92
+ }
93
+
94
+ t_begin "enable sendfile" && {
95
+ echo >> $unicorn_config 'require "sendfile"'
96
+ kill -HUP $rainbows_pid
97
+ test xSTART = x"$(cat $fifo)"
98
+ }
99
+
100
+ t_begin "reread worker pid" && {
101
+ worker_pid=$(curl -sSf http://$listen/pid)
102
+ kill -0 $worker_pid
103
+ }
104
+
105
+ t_begin "restart strace on the worker" && start_strace
106
+
107
+ t_begin "HTTP/1.x GET on static file with sendfile uncorks" && {
108
+ curl -sSf http://$listen/random_blob >/dev/null
109
+ check_TCP_CORK
110
+ }
111
+
112
+ t_begin "killing succeeds" && {
113
+ kill $strace_pid
114
+ wait
115
+ # dbgcat strace_out
116
+ kill $rainbows_pid
117
+ }
118
+
119
+ t_begin "check stderr" && check_stderr
120
+
121
+ t_done
@@ -15,7 +15,7 @@ CONFIG_RU=app_deferred.ru
15
15
  t_begin "setup and start" && {
16
16
  rainbows_setup
17
17
  rtmpfiles deferred_err deferred_out sync_err sync_out
18
- rainbows -D -c $unicorn_config $CONFIG_RU
18
+ fifo=$fifo rainbows -D -c $unicorn_config $CONFIG_RU
19
19
  rainbows_wait_start
20
20
  }
21
21
 
@@ -36,8 +36,20 @@ t_begin "deferred requests run in a different thread" && {
36
36
  test x"$(uniq < $deferred_out)" != x"$sync_thread"
37
37
  }
38
38
 
39
- t_begin "termination signal sent" && {
40
- kill $rainbows_pid
39
+ t_begin "deferred requests run after graceful shutdown" && {
40
+ # XXX sleeping 5s ought to be enough for SIGQUIT to arrive,
41
+ # hard to tell with overloaded systems...
42
+ s=5
43
+ curl -sSf --no-buffer http://$listen/deferred$s \
44
+ >$deferred_out 2>$deferred_err &
45
+ curl_pid=$!
46
+ msg="$(cat $fifo)"
47
+ kill -QUIT $rainbows_pid
48
+ test x"$msg" = x"sleeping ${s}s"
49
+ wait $curl_pid # for curl to finish
50
+ test $? -eq 0
51
+ test ! -s $deferred_err
52
+ test x"$(cat $deferred_out)" = 'xdeferred sleep'
41
53
  }
42
54
 
43
55
  t_begin "no errors in stderr" && check_stderr
@@ -16,7 +16,7 @@
16
16
  lock = File.open(__FILE__, "rb")
17
17
  lock.flock(File::LOCK_EX)
18
18
  Isolate.now!(opts) do
19
- gem 'kgio', '2.10.0'
19
+ gem 'kgio', '2.11.0'
20
20
  gem 'rack', '2.0.1'
21
21
  gem 'kcar', '0.6.0'
22
22
  gem 'raindrops', '0.17.0'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rainbows
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.0.0.5.ge717
4
+ version: 5.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rainbows! hackers
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-11-17 00:00:00.000000000 Z
11
+ date: 2017-01-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -387,6 +387,7 @@ files:
387
387
  - t/t0041-optional-pool-size.sh
388
388
  - t/t0042-client_header_buffer_size.sh
389
389
  - t/t0043-quit-keepalive-disconnect.sh
390
+ - t/t0044-autopush.sh
390
391
  - t/t0045-client_max_header_size.sh
391
392
  - t/t0050-response-body-close-has-env.sh
392
393
  - t/t0100-rack-input-hammer-chunked.sh
@@ -447,12 +448,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
447
448
  version: '0'
448
449
  required_rubygems_version: !ruby/object:Gem::Requirement
449
450
  requirements:
450
- - - ">"
451
+ - - ">="
451
452
  - !ruby/object:Gem::Version
452
- version: 1.3.1
453
+ version: '0'
453
454
  requirements: []
454
455
  rubyforge_project:
455
- rubygems_version: 2.6.6
456
+ rubygems_version: 2.6.8
456
457
  signing_key:
457
458
  specification_version: 4
458
459
  summary: "- unicorn for sleepy apps and slow clients"