passenger 5.0.30 → 5.1.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of passenger might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG +30 -1
- data/CONTRIBUTING.md +1 -1
- data/CONTRIBUTORS +2 -0
- data/bin/passenger-install-nginx-module +18 -13
- data/build/agent.rb +1 -0
- data/build/basics.rb +1 -0
- data/build/cxx_tests.rb +6 -1
- data/build/misc.rb +3 -0
- data/build/packaging.rb +5 -17
- data/build/support/cxx_dependency_map.rb +100 -0
- data/build/support/vendor/cxxcodebuilder/lib/cxxcodebuilder/builder.rb +4 -1
- data/build/test_basics.rb +12 -2
- data/dev/ci/run_travis.sh +6 -2
- data/doc/Users guide Apache.html +7 -2
- data/doc/Users guide Apache.txt +4 -0
- data/resources/templates/error_layout.css +70 -84
- data/resources/templates/error_layout.html.template +84 -93
- data/resources/templates/standalone/http.erb +17 -13
- data/resources/templates/standalone/server.erb +2 -1
- data/resources/templates/undisclosed_error.html.template +52 -51
- data/resources/update_check_client_cert.p12 +0 -0
- data/resources/update_check_client_cert.pem +89 -0
- data/resources/update_check_server_pubkey.pem +14 -0
- data/src/agent/Core/ApplicationPool/ErrorRenderer.h +15 -1
- data/src/agent/Core/Controller.h +3 -2
- data/src/agent/Core/Controller/CheckoutSession.cpp +5 -4
- data/src/agent/Core/Controller/ForwardResponse.cpp +1 -1
- data/src/agent/Core/Controller/InitRequest.cpp +2 -0
- data/src/agent/Core/Controller/InitializationAndShutdown.cpp +1 -0
- data/src/agent/Core/Controller/Request.h +1 -0
- data/src/agent/Core/CoreMain.cpp +99 -2
- data/src/agent/Core/OptionParser.h +18 -1
- data/src/agent/Core/SecurityUpdateChecker.h +559 -0
- data/src/agent/Shared/Base.cpp +6 -1
- data/src/agent/TempDirToucher/TempDirToucherMain.cpp +52 -0
- data/src/agent/Watchdog/InstanceDirToucher.cpp +1 -2
- data/src/agent/Watchdog/WatchdogMain.cpp +31 -40
- data/src/apache2_module/Configuration.cpp +12 -0
- data/src/apache2_module/Configuration.hpp +5 -0
- data/src/apache2_module/ConfigurationCommands.cpp +19 -19
- data/src/apache2_module/ConfigurationCommands.cpp.cxxcodebuilder +2 -2
- data/src/apache2_module/ConfigurationFields.hpp +19 -19
- data/src/apache2_module/ConfigurationFields.hpp.cxxcodebuilder +2 -2
- data/src/apache2_module/ConfigurationSetters.cpp +19 -19
- data/src/apache2_module/ConfigurationSetters.cpp.cxxcodebuilder +2 -2
- data/src/apache2_module/CreateDirConfig.cpp +19 -19
- data/src/apache2_module/CreateDirConfig.cpp.cxxcodebuilder +2 -2
- data/src/apache2_module/Hooks.cpp +10 -1
- data/src/apache2_module/MergeDirConfig.cpp +19 -19
- data/src/apache2_module/MergeDirConfig.cpp.cxxcodebuilder +2 -2
- data/src/apache2_module/SetHeaders.cpp +19 -19
- data/src/apache2_module/SetHeaders.cpp.cxxcodebuilder +2 -2
- data/src/cxx_supportlib/Constants.h +22 -22
- data/src/cxx_supportlib/Constants.h.cxxcodebuilder +4 -1
- data/src/cxx_supportlib/Crypto.cpp +977 -0
- data/src/cxx_supportlib/Crypto.h +147 -0
- data/src/cxx_supportlib/InstanceDirectory.h +55 -2
- data/src/cxx_supportlib/Utils/Curl.h +24 -10
- data/src/cxx_supportlib/Utils/JsonUtils.h +1 -1
- data/src/cxx_supportlib/oxt/detail/spin_lock_darwin.hpp +2 -0
- data/src/cxx_supportlib/vendor-modified/boost/system/error_code.hpp +3 -3
- data/src/cxx_supportlib/vendor-modified/jsoncpp/json-forwards.h +167 -92
- data/src/cxx_supportlib/vendor-modified/jsoncpp/json.h +1827 -1542
- data/src/cxx_supportlib/vendor-modified/jsoncpp/jsoncpp.cpp +4705 -3652
- data/src/cxx_supportlib/vendor-modified/libev/Changes +46 -15
- data/src/cxx_supportlib/vendor-modified/libev/LICENSE +1 -1
- data/src/cxx_supportlib/vendor-modified/libev/Makefile.in +215 -128
- data/src/cxx_supportlib/vendor-modified/libev/aclocal.m4 +466 -275
- data/src/cxx_supportlib/vendor-modified/libev/config.guess +312 -418
- data/src/cxx_supportlib/vendor-modified/libev/config.sub +246 -105
- data/src/cxx_supportlib/vendor-modified/libev/configure +276 -72
- data/src/cxx_supportlib/vendor-modified/libev/configure.ac +2 -1
- data/src/cxx_supportlib/vendor-modified/libev/depcomp +346 -185
- data/src/cxx_supportlib/vendor-modified/libev/ev++.h +1 -1
- data/src/cxx_supportlib/vendor-modified/libev/ev.c +530 -190
- data/src/cxx_supportlib/vendor-modified/libev/ev.h +23 -14
- data/src/cxx_supportlib/vendor-modified/libev/ev_epoll.c +12 -6
- data/src/cxx_supportlib/vendor-modified/libev/ev_kqueue.c +9 -5
- data/src/cxx_supportlib/vendor-modified/libev/ev_poll.c +6 -3
- data/src/cxx_supportlib/vendor-modified/libev/ev_port.c +8 -4
- data/src/cxx_supportlib/vendor-modified/libev/ev_select.c +4 -2
- data/src/cxx_supportlib/vendor-modified/libev/ev_vars.h +3 -2
- data/src/cxx_supportlib/vendor-modified/libev/ev_win32.c +3 -4
- data/src/cxx_supportlib/vendor-modified/libev/install-sh +433 -219
- data/src/cxx_supportlib/vendor-modified/libev/libev.m4 +6 -6
- data/src/cxx_supportlib/vendor-modified/libev/ltmain.sh +2 -2
- data/src/cxx_supportlib/vendor-modified/libev/missing +167 -288
- data/src/cxx_supportlib/vendor-modified/libev/mkinstalldirs +72 -21
- data/src/cxx_supportlib/vendor-modified/modp_b64.cpp +4 -106
- data/src/cxx_supportlib/vendor-modified/modp_b64_data.h +37 -1
- data/src/cxx_supportlib/vendor-modified/modp_b64_strict_aliasing.cpp +119 -0
- data/src/helper-scripts/node-loader.js +72 -1
- data/src/nginx_module/CacheLocationConfig.c +52 -19
- data/src/nginx_module/CacheLocationConfig.c.cxxcodebuilder +2 -2
- data/src/nginx_module/Configuration.c +26 -1
- data/src/nginx_module/Configuration.h +2 -0
- data/src/nginx_module/ConfigurationCommands.c +35 -19
- data/src/nginx_module/ConfigurationCommands.c.cxxcodebuilder +2 -2
- data/src/nginx_module/ContentHandler.c +1 -1
- data/src/nginx_module/CreateLocationConfig.c +22 -19
- data/src/nginx_module/CreateLocationConfig.c.cxxcodebuilder +2 -2
- data/src/nginx_module/LocationConfig.h +21 -19
- data/src/nginx_module/LocationConfig.h.cxxcodebuilder +2 -2
- data/src/nginx_module/MergeLocationConfig.c +25 -19
- data/src/nginx_module/MergeLocationConfig.c.cxxcodebuilder +2 -2
- data/src/nginx_module/ngx_http_passenger_module.c +8 -4
- data/src/ruby_supportlib/phusion_passenger.rb +9 -4
- data/src/ruby_supportlib/phusion_passenger/admin_tools/instance.rb +2 -2
- data/src/ruby_supportlib/phusion_passenger/admin_tools/instance_registry.rb +1 -1
- data/src/ruby_supportlib/phusion_passenger/common_library.rb +13 -0
- data/src/ruby_supportlib/phusion_passenger/config/nginx_engine_compiler.rb +5 -2
- data/src/ruby_supportlib/phusion_passenger/constants.rb +1 -1
- data/src/ruby_supportlib/phusion_passenger/nginx/config_options.rb +15 -3
- data/src/ruby_supportlib/phusion_passenger/platform_info/crypto.rb +51 -0
- data/src/ruby_supportlib/phusion_passenger/platform_info/depcheck_specs/apache2.rb +7 -0
- data/src/ruby_supportlib/phusion_passenger/standalone/config_options_list.rb +17 -0
- data/src/ruby_supportlib/phusion_passenger/standalone/start_command.rb +4 -2
- data/src/ruby_supportlib/phusion_passenger/standalone/start_command/builtin_engine.rb +4 -0
- data/src/ruby_supportlib/phusion_passenger/standalone/start_command/nginx_engine.rb +5 -0
- data/src/ruby_supportlib/phusion_passenger/vendor/crash_watch/app.rb +19 -10
- data/src/ruby_supportlib/phusion_passenger/vendor/crash_watch/base.rb +25 -0
- data/src/ruby_supportlib/phusion_passenger/vendor/crash_watch/gdb_controller.rb +38 -103
- data/src/ruby_supportlib/phusion_passenger/vendor/crash_watch/lldb_controller.rb +178 -0
- data/src/ruby_supportlib/phusion_passenger/vendor/crash_watch/utils.rb +94 -0
- data/src/ruby_supportlib/phusion_passenger/vendor/crash_watch/version.rb +2 -2
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core.rb +2 -2
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/lib/union_station_hooks_core/version_data.rb +2 -2
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/ruby_versions.yml.travis +5 -3
- data/src/ruby_supportlib/phusion_passenger/vendor/union_station_hooks_core/ruby_versions.yml.travis-with-sudo +9 -7
- metadata +14 -4
@@ -1,6 +1,6 @@
|
|
1
1
|
# encoding: binary
|
2
2
|
#
|
3
|
-
# Copyright (c) 2010-
|
3
|
+
# Copyright (c) 2010-2016 Phusion Holding B.V.
|
4
4
|
#
|
5
5
|
# Permission is hereby granted, free of charge, to any person obtaining
|
6
6
|
# a copy of this software and associated documentation files (the
|
@@ -23,6 +23,7 @@
|
|
23
23
|
|
24
24
|
require 'optparse'
|
25
25
|
PhusionPassenger.require_passenger_lib 'vendor/crash_watch/gdb_controller'
|
26
|
+
PhusionPassenger.require_passenger_lib 'vendor/crash_watch/lldb_controller'
|
26
27
|
PhusionPassenger.require_passenger_lib 'vendor/crash_watch/version'
|
27
28
|
|
28
29
|
module CrashWatch
|
@@ -68,7 +69,11 @@ module CrashWatch
|
|
68
69
|
end
|
69
70
|
|
70
71
|
begin
|
71
|
-
|
72
|
+
if !CrashWatch::Utils.gdb_installed? && CrashWatch::Utils.lldb_installed?
|
73
|
+
gdb = CrashWatch::LldbController.new
|
74
|
+
else
|
75
|
+
gdb = CrashWatch::GdbController.new
|
76
|
+
end
|
72
77
|
rescue CrashWatch::Error => e
|
73
78
|
abort e.message
|
74
79
|
end
|
@@ -101,14 +106,18 @@ module CrashWatch
|
|
101
106
|
output.gsub!(/^ (Thread .*):$/, "########### \\1 ###########\n")
|
102
107
|
puts output
|
103
108
|
else
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
109
|
+
if gdb.respond_to?(:wait_until_exit)
|
110
|
+
puts "Monitoring PID #{argv[0]}..."
|
111
|
+
exit_info = gdb.wait_until_exit
|
112
|
+
puts "Process exited at #{Time.now}."
|
113
|
+
puts "Exit code: #{exit_info.exit_code}" if exit_info.exit_code
|
114
|
+
puts "Signal: #{exit_info.signal}" if exit_info.signaled?
|
115
|
+
if exit_info.backtrace
|
116
|
+
puts "Backtrace:"
|
117
|
+
puts " " << exit_info.backtrace.gsub(/\n/, "\n ")
|
118
|
+
end
|
119
|
+
else
|
120
|
+
abort "ERROR: monitoring not supported with LLDB"
|
112
121
|
end
|
113
122
|
end
|
114
123
|
else
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# Copyright (c) 2016 Phusion Holding B.V.
|
2
|
+
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
# a copy of this software and associated documentation files (the
|
5
|
+
# "Software"), to deal in the Software without restriction, including
|
6
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
# the following conditions:
|
10
|
+
#
|
11
|
+
# The above copyright notice and this permission notice shall be
|
12
|
+
# included in all copies or substantial portions of the Software.
|
13
|
+
#
|
14
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
|
+
|
22
|
+
module CrashWatch
|
23
|
+
class Error < StandardError
|
24
|
+
end
|
25
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# encoding: binary
|
2
2
|
#
|
3
|
-
# Copyright (c) 2010-
|
3
|
+
# Copyright (c) 2010-2016 Phusion Holding B.V.
|
4
4
|
#
|
5
5
|
# Permission is hereby granted, free of charge, to any person obtaining
|
6
6
|
# a copy of this software and associated documentation files (the
|
@@ -22,11 +22,10 @@
|
|
22
22
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
23
23
|
|
24
24
|
require 'rbconfig'
|
25
|
+
PhusionPassenger.require_passenger_lib 'vendor/crash_watch/base'
|
26
|
+
PhusionPassenger.require_passenger_lib 'vendor/crash_watch/utils'
|
25
27
|
|
26
28
|
module CrashWatch
|
27
|
-
class Error < StandardError
|
28
|
-
end
|
29
|
-
|
30
29
|
class GdbNotFound < Error
|
31
30
|
end
|
32
31
|
|
@@ -36,28 +35,28 @@ module CrashWatch
|
|
36
35
|
class GdbController
|
37
36
|
class ExitInfo
|
38
37
|
attr_reader :exit_code, :signal, :backtrace, :snapshot
|
39
|
-
|
38
|
+
|
40
39
|
def initialize(exit_code, signal, backtrace, snapshot)
|
41
40
|
@exit_code = exit_code
|
42
41
|
@signal = signal
|
43
42
|
@backtrace = backtrace
|
44
43
|
@snapshot = snapshot
|
45
44
|
end
|
46
|
-
|
45
|
+
|
47
46
|
def signaled?
|
48
47
|
!!@signal
|
49
48
|
end
|
50
49
|
end
|
51
|
-
|
50
|
+
|
52
51
|
END_OF_RESPONSE_MARKER = '--------END_OF_RESPONSE--------'
|
53
|
-
|
52
|
+
|
54
53
|
attr_accessor :debug
|
55
54
|
|
56
55
|
def initialize
|
57
|
-
@pid, @in, @out = popen_command(find_gdb, "-n", "-q")
|
56
|
+
@pid, @in, @out = Utils.popen_command(find_gdb, "-n", "-q")
|
58
57
|
execute("set prompt ")
|
59
58
|
end
|
60
|
-
|
59
|
+
|
61
60
|
def execute(command_string, timeout = nil)
|
62
61
|
raise "GDB session is already closed" if !@pid
|
63
62
|
puts "gdb write #{command_string.inspect}" if @debug
|
@@ -86,11 +85,11 @@ module CrashWatch
|
|
86
85
|
end
|
87
86
|
result
|
88
87
|
end
|
89
|
-
|
88
|
+
|
90
89
|
def closed?
|
91
90
|
!@pid
|
92
91
|
end
|
93
|
-
|
92
|
+
|
94
93
|
def close
|
95
94
|
if !closed?
|
96
95
|
begin
|
@@ -106,7 +105,7 @@ module CrashWatch
|
|
106
105
|
end
|
107
106
|
end
|
108
107
|
end
|
109
|
-
|
108
|
+
|
110
109
|
def close!
|
111
110
|
if !closed?
|
112
111
|
@in.close
|
@@ -116,86 +115,48 @@ module CrashWatch
|
|
116
115
|
@pid = nil
|
117
116
|
end
|
118
117
|
end
|
119
|
-
|
118
|
+
|
120
119
|
def attach(pid)
|
121
120
|
pid = pid.to_s.strip
|
122
121
|
raise ArgumentError if pid.empty?
|
123
122
|
result = execute("attach #{pid}")
|
124
123
|
result !~ /(No such process|Unable to access task|Operation not permitted)/
|
125
124
|
end
|
126
|
-
|
127
|
-
def call(code)
|
128
|
-
result = execute("call #{code}")
|
129
|
-
result =~ /= (.*)$/
|
130
|
-
$1
|
131
|
-
end
|
132
|
-
|
125
|
+
|
133
126
|
def program_counter
|
134
127
|
execute("p/x $pc").gsub(/.* = /, '')
|
135
128
|
end
|
136
|
-
|
129
|
+
|
137
130
|
def current_thread
|
138
131
|
execute("thread") =~ /Current thread is (.+?) /
|
139
132
|
$1
|
140
133
|
end
|
141
|
-
|
134
|
+
|
142
135
|
def current_thread_backtrace
|
143
136
|
execute("bt full").strip
|
144
137
|
end
|
145
|
-
|
138
|
+
|
146
139
|
def all_threads_backtraces
|
147
140
|
execute("thread apply all bt full").strip
|
148
141
|
end
|
149
|
-
|
150
|
-
def ruby_backtrace
|
151
|
-
filename = "/tmp/gdb-capture.#{@pid}.txt"
|
152
|
-
|
153
|
-
orig_stdout_fd_copy = call("(int) dup(1)")
|
154
|
-
new_stdout = call(%Q{(void *) fopen("#{filename}", "w")})
|
155
|
-
new_stdout_fd = call("(int) fileno(#{new_stdout})")
|
156
|
-
call("(int) dup2(#{new_stdout_fd}, 1)")
|
157
|
-
|
158
|
-
# Let's hope stdout is set to line buffered or unbuffered mode...
|
159
|
-
call("(void) rb_backtrace()")
|
160
|
-
|
161
|
-
call("(int) dup2(#{orig_stdout_fd_copy}, 1)")
|
162
|
-
call("(int) fclose(#{new_stdout})")
|
163
|
-
call("(int) close(#{orig_stdout_fd_copy})")
|
164
|
-
|
165
|
-
if File.exist?(filename)
|
166
|
-
result = File.read(filename)
|
167
|
-
result.strip!
|
168
|
-
if result.empty?
|
169
|
-
nil
|
170
|
-
else
|
171
|
-
result
|
172
|
-
end
|
173
|
-
else
|
174
|
-
nil
|
175
|
-
end
|
176
|
-
ensure
|
177
|
-
if filename
|
178
|
-
File.unlink(filename) rescue nil
|
179
|
-
end
|
180
|
-
end
|
181
|
-
|
142
|
+
|
182
143
|
def wait_until_exit
|
183
144
|
execute("break _exit")
|
184
|
-
|
145
|
+
|
185
146
|
signal = nil
|
186
147
|
backtraces = nil
|
187
148
|
snapshot = nil
|
188
|
-
|
149
|
+
|
189
150
|
while true
|
190
151
|
result = execute("continue")
|
191
|
-
if result =~ /^Program received signal (.+?),/
|
192
|
-
signal = $
|
152
|
+
if result =~ /^(Program|Thread .*) received signal (.+?),/
|
153
|
+
signal = $2
|
193
154
|
backtraces = execute("thread apply all bt full").strip
|
194
155
|
if backtraces.empty?
|
195
156
|
backtraces = execute("bt full").strip
|
196
157
|
end
|
197
158
|
snapshot = yield(self) if block_given?
|
198
|
-
|
159
|
+
|
199
160
|
# This signal may or may not be immediately fatal; the
|
200
161
|
# signal might be ignored by the process, or the process
|
201
162
|
# has some clever signal handler that fixes the state,
|
@@ -204,12 +165,12 @@ module CrashWatch
|
|
204
165
|
# the next machine instruction.
|
205
166
|
old_program_counter = program_counter
|
206
167
|
result = execute("stepi")
|
207
|
-
if result =~ /^Program received signal .+?,/
|
168
|
+
if result =~ /^(Program|Thread .*) received signal .+?,/
|
208
169
|
# Yes, it was fatal. Here we don't care whether the
|
209
170
|
# instruction caused a different signal. The last
|
210
171
|
# one is probably what we're interested in.
|
211
172
|
return ExitInfo.new(nil, signal, backtraces, snapshot)
|
212
|
-
elsif result =~ /^Program (terminated|exited)/ || result =~ /^Breakpoint .*? _exit/
|
173
|
+
elsif result =~ /^Program (terminated|exited)/ || result =~ /^Breakpoint .*? (__GI_)?_exit/
|
213
174
|
# Running the next instruction causes the program to terminate.
|
214
175
|
# Not sure what's going on but the previous signal and
|
215
176
|
# backtrace is probably what we're interested in.
|
@@ -230,7 +191,8 @@ module CrashWatch
|
|
230
191
|
else
|
231
192
|
return ExitInfo.new(nil, signal, nil, snapshot)
|
232
193
|
end
|
233
|
-
elsif result =~
|
194
|
+
elsif result =~ /Breakpoint .*? (__GI_)?_exit (\(status=(\d+)\))?/
|
195
|
+
status_param = $3
|
234
196
|
backtraces = execute("thread apply all bt full").strip
|
235
197
|
if backtraces.empty?
|
236
198
|
backtraces = execute("bt full").strip
|
@@ -240,53 +202,26 @@ module CrashWatch
|
|
240
202
|
# even though the process exited. Kernel bug? In any case,
|
241
203
|
# we put a timeout here so that we don't wait indefinitely.
|
242
204
|
result = execute("continue", 10)
|
243
|
-
if result =~ /^Program exited with code (\d+)
|
244
|
-
return ExitInfo.new($
|
245
|
-
elsif result =~ /^Program exited normally/
|
205
|
+
if result =~ /^(Program|.*process .*) exited with code (\d+)/
|
206
|
+
return ExitInfo.new($2.to_i, nil, backtraces, snapshot)
|
207
|
+
elsif result =~ /^(Program|.*process .*) exited normally/
|
246
208
|
return ExitInfo.new(0, nil, backtraces, snapshot)
|
247
|
-
|
209
|
+
elsif status_param.nil? || status_param.empty?
|
248
210
|
return ExitInfo.new(nil, nil, backtraces, snapshot)
|
211
|
+
else
|
212
|
+
return ExitInfo.new(status_param.to_i, nil, backtraces, snapshot)
|
249
213
|
end
|
250
|
-
elsif result =~ /^Program exited with code (\d+)\.$/
|
251
|
-
return ExitInfo.new($
|
252
|
-
elsif result =~ /^Program exited normally/
|
214
|
+
elsif result =~ /^(Program|.*process .*) exited with code (\d+)\.$/
|
215
|
+
return ExitInfo.new($2.to_i, nil, nil, nil)
|
216
|
+
elsif result =~ /^(Program|.*process .*) exited normally/
|
253
217
|
return ExitInfo.new(0, nil, nil, nil)
|
254
218
|
else
|
255
219
|
return ExitInfo.new(nil, nil, nil, nil)
|
256
220
|
end
|
257
221
|
end
|
258
222
|
end
|
259
|
-
|
260
|
-
private
|
261
|
-
def popen_command(*command)
|
262
|
-
a, b = IO.pipe
|
263
|
-
c, d = IO.pipe
|
264
|
-
if Process.respond_to?(:spawn)
|
265
|
-
args = command.dup
|
266
|
-
args << {
|
267
|
-
STDIN => a,
|
268
|
-
STDOUT => d,
|
269
|
-
STDERR => d,
|
270
|
-
:close_others => true
|
271
|
-
}
|
272
|
-
pid = Process.spawn(*args)
|
273
|
-
else
|
274
|
-
pid = fork do
|
275
|
-
STDIN.reopen(a)
|
276
|
-
STDOUT.reopen(d)
|
277
|
-
STDERR.reopen(d)
|
278
|
-
b.close
|
279
|
-
c.close
|
280
|
-
exec(*command)
|
281
|
-
end
|
282
|
-
end
|
283
|
-
a.close
|
284
|
-
d.close
|
285
|
-
b.binmode
|
286
|
-
c.binmode
|
287
|
-
[pid, b, c]
|
288
|
-
end
|
289
223
|
|
224
|
+
private
|
290
225
|
def find_gdb
|
291
226
|
result = nil
|
292
227
|
if ENV['GDB'] && File.executable?(ENV['GDB'])
|
@@ -328,7 +263,7 @@ module CrashWatch
|
|
328
263
|
end
|
329
264
|
elsif result.nil?
|
330
265
|
raise GdbNotFound,
|
331
|
-
"*** ERROR ***: 'gdb' not found. Please install it (and if using Nginx " +
|
266
|
+
"*** ERROR ***: 'gdb' not found. Please install it (and if using Nginx " +
|
332
267
|
"ensure that PATH isn't filtered out, see also its \"env\" option).\n" +
|
333
268
|
" Debian/Ubuntu: sudo apt-get install gdb\n" +
|
334
269
|
"RedHat/CentOS/Fedora: sudo yum install gdb\n" +
|
@@ -0,0 +1,178 @@
|
|
1
|
+
# encoding: binary
|
2
|
+
#
|
3
|
+
# Copyright (c) 2016 Phusion Holding B.V.
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
# a copy of this software and associated documentation files (the
|
7
|
+
# "Software"), to deal in the Software without restriction, including
|
8
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
# the following conditions:
|
12
|
+
#
|
13
|
+
# The above copyright notice and this permission notice shall be
|
14
|
+
# included in all copies or substantial portions of the Software.
|
15
|
+
#
|
16
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
23
|
+
|
24
|
+
require 'rbconfig'
|
25
|
+
PhusionPassenger.require_passenger_lib 'vendor/crash_watch/base'
|
26
|
+
PhusionPassenger.require_passenger_lib 'vendor/crash_watch/utils'
|
27
|
+
|
28
|
+
module CrashWatch
|
29
|
+
class LldbNotFound < Error
|
30
|
+
end
|
31
|
+
|
32
|
+
class LldbController
|
33
|
+
class ExitInfo
|
34
|
+
attr_reader :exit_code, :signal, :backtrace, :snapshot
|
35
|
+
|
36
|
+
def initialize(exit_code, signal, backtrace, snapshot)
|
37
|
+
@exit_code = exit_code
|
38
|
+
@signal = signal
|
39
|
+
@backtrace = backtrace
|
40
|
+
@snapshot = snapshot
|
41
|
+
end
|
42
|
+
|
43
|
+
def signaled?
|
44
|
+
!!@signal
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
END_OF_RESPONSE_MARKER = '--------END_OF_RESPONSE--------'
|
49
|
+
|
50
|
+
attr_accessor :debug
|
51
|
+
|
52
|
+
def initialize
|
53
|
+
@pid, @in, @out = Utils.popen_command(find_lldb, "-x")
|
54
|
+
execute("settings set prompt 'LLDB:'")
|
55
|
+
execute("settings set auto-confirm false")
|
56
|
+
end
|
57
|
+
|
58
|
+
def execute(command_string, timeout = nil)
|
59
|
+
raise "LLDB session is already closed" if !@pid
|
60
|
+
puts "lldb write #{command_string.inspect}" if @debug
|
61
|
+
marker = "\n#{END_OF_RESPONSE_MARKER}\n"
|
62
|
+
@in.puts(command_string)
|
63
|
+
@in.puts("script print #{marker.inspect}")
|
64
|
+
done = false
|
65
|
+
result = []
|
66
|
+
while !done
|
67
|
+
begin
|
68
|
+
if select([@out], nil, nil, timeout)
|
69
|
+
line = @out.readline.chomp
|
70
|
+
line.sub!(/^LLDB:/, '')
|
71
|
+
puts "lldb read #{line.inspect}" if @debug
|
72
|
+
if line == "#{END_OF_RESPONSE_MARKER}"
|
73
|
+
done = true
|
74
|
+
else
|
75
|
+
result << line
|
76
|
+
end
|
77
|
+
else
|
78
|
+
close!
|
79
|
+
done = true
|
80
|
+
result = nil
|
81
|
+
end
|
82
|
+
rescue EOFError
|
83
|
+
done = true
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
if result
|
88
|
+
# Remove echo of the command string
|
89
|
+
result.slice!(0, 2)
|
90
|
+
# Remove echo of the marker print command
|
91
|
+
result.pop
|
92
|
+
result.pop
|
93
|
+
|
94
|
+
result.join("\n") << "\n"
|
95
|
+
else
|
96
|
+
nil
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def closed?
|
101
|
+
!@pid
|
102
|
+
end
|
103
|
+
|
104
|
+
def close
|
105
|
+
if !closed?
|
106
|
+
begin
|
107
|
+
execute("process detach", 5) if !closed?
|
108
|
+
execute("quit", 5) if !closed?
|
109
|
+
rescue Errno::EPIPE
|
110
|
+
end
|
111
|
+
if !closed?
|
112
|
+
@in.close
|
113
|
+
@out.close
|
114
|
+
Process.waitpid(@pid)
|
115
|
+
@pid = nil
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def close!
|
121
|
+
if !closed?
|
122
|
+
@in.close
|
123
|
+
@out.close
|
124
|
+
Process.kill('KILL', @pid)
|
125
|
+
Process.waitpid(@pid)
|
126
|
+
@pid = nil
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def attach(pid)
|
131
|
+
pid = pid.to_s.strip
|
132
|
+
raise ArgumentError if pid.empty?
|
133
|
+
result = execute("attach -p #{pid}")
|
134
|
+
result !~ /(unable to attach|cannot attach)/
|
135
|
+
end
|
136
|
+
|
137
|
+
def program_counter
|
138
|
+
execute("p/x $pc").gsub(/.* = /, '')
|
139
|
+
end
|
140
|
+
|
141
|
+
def current_thread
|
142
|
+
execute("thread info") =~ /^thread #(.+?): /
|
143
|
+
$1
|
144
|
+
end
|
145
|
+
|
146
|
+
def current_thread_backtrace
|
147
|
+
execute("bt").strip
|
148
|
+
end
|
149
|
+
|
150
|
+
def all_threads_backtraces
|
151
|
+
execute("bt all").strip
|
152
|
+
end
|
153
|
+
|
154
|
+
private
|
155
|
+
def find_lldb
|
156
|
+
result = nil
|
157
|
+
if ENV['LLDB'] && File.executable?(ENV['LLDB'])
|
158
|
+
result = ENV['LLDB']
|
159
|
+
else
|
160
|
+
ENV['PATH'].to_s.split(/:+/).each do |path|
|
161
|
+
filename = "#{path}/lldb"
|
162
|
+
if File.file?(filename) && File.executable?(filename)
|
163
|
+
result = filename
|
164
|
+
break
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
puts "Found lldb at: #{result}" if result
|
170
|
+
|
171
|
+
if result.nil?
|
172
|
+
raise LldbNotFound
|
173
|
+
else
|
174
|
+
result
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|