passenger 5.0.0.beta3 → 5.0.0.rc1

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.

Files changed (218) hide show
  1. checksums.yaml +8 -8
  2. checksums.yaml.gz.asc +7 -7
  3. data.tar.gz.asc +7 -7
  4. data/.editorconfig +11 -5
  5. data/CHANGELOG +38 -0
  6. data/CONTRIBUTING.md +1 -4
  7. data/Gemfile +0 -1
  8. data/Gemfile.lock +0 -2
  9. data/Rakefile +33 -33
  10. data/bin/passenger +1 -1
  11. data/bin/passenger-config +1 -1
  12. data/bin/passenger-install-apache2-module +800 -800
  13. data/bin/passenger-install-nginx-module +592 -592
  14. data/bin/passenger-memory-stats +127 -127
  15. data/bin/passenger-status +216 -216
  16. data/build/agents.rb +127 -127
  17. data/build/apache2.rb +87 -87
  18. data/build/basics.rb +60 -60
  19. data/build/common_library.rb +165 -165
  20. data/build/cplusplus_support.rb +51 -51
  21. data/build/cxx_tests.rb +268 -268
  22. data/build/debian.rb +143 -143
  23. data/build/documentation.rb +58 -58
  24. data/build/integration_tests.rb +81 -81
  25. data/build/misc.rb +132 -132
  26. data/build/nginx.rb +20 -20
  27. data/build/node_tests.rb +7 -7
  28. data/build/oxt_tests.rb +14 -14
  29. data/build/packaging.rb +570 -570
  30. data/build/preprocessor.rb +260 -260
  31. data/build/rake_extensions.rb +71 -71
  32. data/build/ruby_extension.rb +29 -29
  33. data/build/ruby_tests.rb +6 -6
  34. data/build/test_basics.rb +37 -37
  35. data/debian.template/control.template +3 -5
  36. data/dev/copy_boost_headers +134 -134
  37. data/dev/install_scripts_bootstrap_code.rb +25 -25
  38. data/dev/list_tests +20 -20
  39. data/dev/ruby_server.rb +223 -223
  40. data/dev/runner +18 -18
  41. data/doc/ServerOptimizationGuide.txt.md +55 -2
  42. data/doc/Users guide Nginx.txt +0 -26
  43. data/doc/Users guide Standalone.txt +5 -1
  44. data/doc/users_guide_snippets/tips.txt +9 -0
  45. data/ext/common/ApplicationPool2/Group.h +23 -11
  46. data/ext/common/ApplicationPool2/Implementation.cpp +32 -7
  47. data/ext/common/ApplicationPool2/Pool.h +22 -17
  48. data/ext/common/ApplicationPool2/SmartSpawner.h +4 -1
  49. data/ext/common/ApplicationPool2/Spawner.h +1 -1
  50. data/ext/common/Constants.h +1 -1
  51. data/ext/common/agents/Base.cpp +35 -20
  52. data/ext/common/agents/HelperAgent/Main.cpp +8 -1
  53. data/ext/common/agents/HelperAgent/OptionParser.h +18 -4
  54. data/ext/common/agents/HelperAgent/RequestHandler.h +2 -83
  55. data/ext/common/agents/HelperAgent/RequestHandler/ForwardResponse.cpp +54 -1
  56. data/ext/common/agents/HelperAgent/RequestHandler/InitRequest.cpp +7 -4
  57. data/ext/common/agents/Main.cpp +1 -1
  58. data/ext/common/agents/Watchdog/Main.cpp +54 -19
  59. data/ext/nginx/Configuration.c +7 -0
  60. data/ext/nginx/ContentHandler.c +9 -1
  61. data/helper-scripts/backtrace-sanitizer.rb +106 -87
  62. data/helper-scripts/crash-watch.rb +32 -0
  63. data/helper-scripts/download_binaries/extconf.rb +38 -38
  64. data/helper-scripts/meteor-loader.rb +107 -107
  65. data/helper-scripts/prespawn +101 -101
  66. data/helper-scripts/rack-loader.rb +96 -96
  67. data/helper-scripts/rack-preloader.rb +137 -137
  68. data/lib/phusion_passenger.rb +292 -292
  69. data/lib/phusion_passenger/abstract_installer.rb +438 -438
  70. data/lib/phusion_passenger/active_support3_extensions/init.rb +168 -170
  71. data/lib/phusion_passenger/admin_tools.rb +20 -20
  72. data/lib/phusion_passenger/admin_tools/instance.rb +178 -178
  73. data/lib/phusion_passenger/admin_tools/instance_registry.rb +61 -61
  74. data/lib/phusion_passenger/admin_tools/memory_stats.rb +267 -267
  75. data/lib/phusion_passenger/apache2/config_options.rb +182 -182
  76. data/lib/phusion_passenger/common_library.rb +479 -485
  77. data/lib/phusion_passenger/config/about_command.rb +161 -161
  78. data/lib/phusion_passenger/config/admin_command_command.rb +129 -129
  79. data/lib/phusion_passenger/config/agent_compiler.rb +121 -121
  80. data/lib/phusion_passenger/config/build_native_support_command.rb +43 -43
  81. data/lib/phusion_passenger/config/command.rb +25 -25
  82. data/lib/phusion_passenger/config/compile_agent_command.rb +62 -62
  83. data/lib/phusion_passenger/config/compile_nginx_engine_command.rb +88 -73
  84. data/lib/phusion_passenger/config/detach_process_command.rb +72 -72
  85. data/lib/phusion_passenger/config/download_agent_command.rb +246 -227
  86. data/lib/phusion_passenger/config/download_nginx_engine_command.rb +245 -224
  87. data/lib/phusion_passenger/config/install_agent_command.rb +144 -132
  88. data/lib/phusion_passenger/config/install_standalone_runtime_command.rb +205 -185
  89. data/lib/phusion_passenger/config/installation_utils.rb +204 -204
  90. data/lib/phusion_passenger/config/list_instances_command.rb +64 -64
  91. data/lib/phusion_passenger/config/main.rb +152 -152
  92. data/lib/phusion_passenger/config/nginx_engine_compiler.rb +319 -300
  93. data/lib/phusion_passenger/config/reopen_logs_command.rb +67 -67
  94. data/lib/phusion_passenger/config/restart_app_command.rb +155 -155
  95. data/lib/phusion_passenger/config/system_metrics_command.rb +13 -13
  96. data/lib/phusion_passenger/config/utils.rb +95 -95
  97. data/lib/phusion_passenger/config/validate_install_command.rb +198 -198
  98. data/lib/phusion_passenger/console_text_template.rb +25 -25
  99. data/lib/phusion_passenger/constants.rb +90 -90
  100. data/lib/phusion_passenger/debug_logging.rb +106 -106
  101. data/lib/phusion_passenger/loader_shared_helpers.rb +447 -432
  102. data/lib/phusion_passenger/message_channel.rb +312 -312
  103. data/lib/phusion_passenger/message_client.rb +176 -176
  104. data/lib/phusion_passenger/native_support.rb +369 -369
  105. data/lib/phusion_passenger/nginx/config_options.rb +297 -297
  106. data/lib/phusion_passenger/packaging.rb +131 -131
  107. data/lib/phusion_passenger/platform_info.rb +360 -360
  108. data/lib/phusion_passenger/platform_info/apache.rb +767 -767
  109. data/lib/phusion_passenger/platform_info/apache_detector.rb +199 -199
  110. data/lib/phusion_passenger/platform_info/binary_compatibility.rb +107 -107
  111. data/lib/phusion_passenger/platform_info/compiler.rb +570 -570
  112. data/lib/phusion_passenger/platform_info/curl.rb +32 -32
  113. data/lib/phusion_passenger/platform_info/cxx_portability.rb +188 -188
  114. data/lib/phusion_passenger/platform_info/depcheck.rb +372 -372
  115. data/lib/phusion_passenger/platform_info/depcheck_specs/apache2.rb +109 -109
  116. data/lib/phusion_passenger/platform_info/depcheck_specs/compiler_toolchain.rb +4 -4
  117. data/lib/phusion_passenger/platform_info/depcheck_specs/gems.rb +10 -34
  118. data/lib/phusion_passenger/platform_info/depcheck_specs/libs.rb +101 -101
  119. data/lib/phusion_passenger/platform_info/depcheck_specs/ruby.rb +5 -5
  120. data/lib/phusion_passenger/platform_info/depcheck_specs/utilities.rb +13 -13
  121. data/lib/phusion_passenger/platform_info/linux.rb +55 -55
  122. data/lib/phusion_passenger/platform_info/operating_system.rb +149 -149
  123. data/lib/phusion_passenger/platform_info/ruby.rb +468 -448
  124. data/lib/phusion_passenger/platform_info/zlib.rb +9 -9
  125. data/lib/phusion_passenger/plugin.rb +66 -66
  126. data/lib/phusion_passenger/preloader_shared_helpers.rb +126 -126
  127. data/lib/phusion_passenger/public_api.rb +191 -191
  128. data/lib/phusion_passenger/rack/out_of_band_gc.rb +93 -94
  129. data/lib/phusion_passenger/rack/thread_handler_extension.rb +231 -227
  130. data/lib/phusion_passenger/request_handler.rb +567 -577
  131. data/lib/phusion_passenger/request_handler/thread_handler.rb +379 -381
  132. data/lib/phusion_passenger/ruby_core_enhancements.rb +86 -86
  133. data/lib/phusion_passenger/ruby_core_io_enhancements.rb +74 -74
  134. data/lib/phusion_passenger/simple_benchmarking.rb +25 -25
  135. data/lib/phusion_passenger/standalone/app_finder.rb +153 -150
  136. data/lib/phusion_passenger/standalone/command.rb +44 -40
  137. data/lib/phusion_passenger/standalone/config_utils.rb +53 -53
  138. data/lib/phusion_passenger/standalone/control_utils.rb +38 -59
  139. data/lib/phusion_passenger/standalone/main.rb +73 -73
  140. data/lib/phusion_passenger/standalone/start_command.rb +697 -685
  141. data/lib/phusion_passenger/standalone/start_command/builtin_engine.rb +193 -155
  142. data/lib/phusion_passenger/standalone/start_command/nginx_engine.rb +162 -133
  143. data/lib/phusion_passenger/standalone/status_command.rb +64 -64
  144. data/lib/phusion_passenger/standalone/stop_command.rb +72 -72
  145. data/lib/phusion_passenger/standalone/version_command.rb +9 -9
  146. data/lib/phusion_passenger/union_station/connection.rb +32 -32
  147. data/lib/phusion_passenger/union_station/core.rb +251 -251
  148. data/lib/phusion_passenger/union_station/transaction.rb +126 -126
  149. data/lib/phusion_passenger/utils.rb +199 -167
  150. data/lib/phusion_passenger/utils/ansi_colors.rb +128 -128
  151. data/lib/phusion_passenger/utils/download.rb +196 -196
  152. data/lib/phusion_passenger/utils/file_system_watcher.rb +158 -158
  153. data/lib/phusion_passenger/utils/hosts_file_parser.rb +101 -101
  154. data/lib/phusion_passenger/utils/lock.rb +31 -31
  155. data/lib/phusion_passenger/utils/native_support_utils.rb +31 -31
  156. data/lib/phusion_passenger/utils/progress_bar.rb +26 -26
  157. data/lib/phusion_passenger/utils/shellwords.rb +20 -20
  158. data/lib/phusion_passenger/utils/terminal_choice_menu.rb +206 -206
  159. data/lib/phusion_passenger/utils/unseekable_socket.rb +272 -272
  160. data/lib/phusion_passenger/vendor/crash_watch/app.rb +129 -0
  161. data/lib/phusion_passenger/vendor/crash_watch/gdb_controller.rb +341 -0
  162. data/lib/phusion_passenger/vendor/crash_watch/version.rb +24 -0
  163. data/lib/phusion_passenger/vendor/daemon_controller.rb +877 -0
  164. data/lib/phusion_passenger/vendor/daemon_controller/lock_file.rb +127 -0
  165. data/lib/phusion_passenger/vendor/daemon_controller/spawn.rb +26 -0
  166. data/lib/phusion_passenger/vendor/daemon_controller/version.rb +29 -0
  167. data/packaging/rpm/passenger_spec/passenger.spec.template +0 -1
  168. data/passenger.gemspec +0 -1
  169. data/resources/templates/config/nginx_engine_compiler/possible_solutions_for_download_and_extraction_problems.txt.erb +27 -0
  170. data/resources/templates/standalone/config.erb +19 -15
  171. data/test/integration_tests/apache2_tests.rb +566 -566
  172. data/test/integration_tests/downloaded_binaries_tests.rb +126 -125
  173. data/test/integration_tests/native_packaging_spec.rb +296 -296
  174. data/test/integration_tests/nginx_tests.rb +393 -393
  175. data/test/integration_tests/shared/example_webapp_tests.rb +282 -280
  176. data/test/integration_tests/source_packaging_test.rb +138 -138
  177. data/test/integration_tests/spec_helper.rb +5 -5
  178. data/test/integration_tests/standalone_tests.rb +367 -367
  179. data/test/ruby/debug_logging_spec.rb +133 -133
  180. data/test/ruby/message_channel_spec.rb +186 -186
  181. data/test/ruby/rack/loader_spec.rb +28 -28
  182. data/test/ruby/rack/preloader_spec.rb +34 -34
  183. data/test/ruby/rails3.0/loader_spec.rb +12 -12
  184. data/test/ruby/rails3.0/preloader_spec.rb +18 -18
  185. data/test/ruby/rails3.1/loader_spec.rb +12 -12
  186. data/test/ruby/rails3.1/preloader_spec.rb +18 -18
  187. data/test/ruby/rails3.2/loader_spec.rb +12 -12
  188. data/test/ruby/rails3.2/preloader_spec.rb +18 -18
  189. data/test/ruby/rails4.0/loader_spec.rb +12 -12
  190. data/test/ruby/rails4.0/preloader_spec.rb +18 -18
  191. data/test/ruby/rails4.1/loader_spec.rb +12 -12
  192. data/test/ruby/rails4.1/preloader_spec.rb +18 -18
  193. data/test/ruby/request_handler_spec.rb +730 -730
  194. data/test/ruby/shared/loader_sharedspec.rb +224 -224
  195. data/test/ruby/shared/rails/union_station_extensions_sharedspec.rb +327 -327
  196. data/test/ruby/shared/ruby_loader_sharedspec.rb +47 -47
  197. data/test/ruby/spec_helper.rb +65 -65
  198. data/test/ruby/standalone/runtime_installer_spec.rb +384 -384
  199. data/test/ruby/union_station_spec.rb +276 -276
  200. data/test/ruby/utils/file_system_watcher_spec.rb +220 -220
  201. data/test/ruby/utils/hosts_file_parser.rb +248 -248
  202. data/test/ruby/utils/tee_input_spec.rb +215 -215
  203. data/test/ruby/utils/unseekable_socket_spec.rb +57 -57
  204. data/test/ruby/utils_spec.rb +21 -21
  205. data/test/stub/rack/config.ru +87 -87
  206. data/test/stub/rack/library.rb +8 -8
  207. data/test/stub/rack/start.rb +30 -30
  208. data/test/support/apache2_controller.rb +191 -191
  209. data/test/support/nginx_controller.rb +90 -99
  210. data/test/support/placebo-preloader.rb +57 -57
  211. data/test/support/test_helper.rb +435 -435
  212. metadata +11 -21
  213. metadata.gz.asc +7 -7
  214. data/lib/phusion_passenger/standalone/command2.rb +0 -292
  215. data/lib/phusion_passenger/standalone/start2_command.rb +0 -799
  216. data/resources/templates/standalone/download_tool_missing.txt.erb +0 -18
  217. data/resources/templates/standalone/possible_solutions_for_download_and_extraction_problems.txt.erb +0 -17
  218. data/resources/templates/standalone/run_installer_as_root.txt.erb +0 -8
@@ -23,146 +23,146 @@
23
23
 
24
24
  module PhusionPassenger
25
25
 
26
- module Packaging
27
- # A list of HTML files that are generated with Asciidoc.
28
- ASCII_DOCS = [
29
- 'doc/Users guide.html',
30
- 'doc/Users guide Apache.html',
31
- 'doc/Users guide Nginx.html',
32
- 'doc/Users guide Standalone.html',
33
- 'doc/Security of user switching support.html',
34
- 'doc/Design and Architecture.html'
35
- ]
26
+ module Packaging
27
+ # A list of HTML files that are generated with Asciidoc.
28
+ ASCII_DOCS = [
29
+ 'doc/Users guide.html',
30
+ 'doc/Users guide Apache.html',
31
+ 'doc/Users guide Nginx.html',
32
+ 'doc/Users guide Standalone.html',
33
+ 'doc/Security of user switching support.html',
34
+ 'doc/Design and Architecture.html'
35
+ ]
36
36
 
37
- # Files that must be generated before packaging.
38
- PREGENERATED_FILES = [
39
- 'ext/common/Constants.h',
40
- 'doc/Packaging.html',
41
- 'doc/CloudLicensingConfiguration.html',
42
- 'doc/ServerOptimizationGuide.html'
43
- ] + ASCII_DOCS
37
+ # Files that must be generated before packaging.
38
+ PREGENERATED_FILES = [
39
+ 'ext/common/Constants.h',
40
+ 'doc/Packaging.html',
41
+ 'doc/CloudLicensingConfiguration.html',
42
+ 'doc/ServerOptimizationGuide.html'
43
+ ] + ASCII_DOCS
44
44
 
45
- USER_EXECUTABLES = [
46
- 'passenger',
47
- 'passenger-install-apache2-module',
48
- 'passenger-install-nginx-module',
49
- 'passenger-config'
50
- ]
45
+ USER_EXECUTABLES = [
46
+ 'passenger',
47
+ 'passenger-install-apache2-module',
48
+ 'passenger-install-nginx-module',
49
+ 'passenger-config'
50
+ ]
51
51
 
52
- SUPER_USER_EXECUTABLES = [
53
- 'passenger-status',
54
- 'passenger-memory-stats'
55
- ]
52
+ SUPER_USER_EXECUTABLES = [
53
+ 'passenger-status',
54
+ 'passenger-memory-stats'
55
+ ]
56
56
 
57
- # Used during native packaging. Specifies executables for
58
- # which the shebang should NOT be set to #!/usr/bin/ruby,
59
- # so that these executables can be run with any Ruby interpreter
60
- # the user desires.
61
- EXECUTABLES_WITH_FREE_RUBY = [
62
- 'passenger',
63
- 'passenger-config',
64
- 'passenger-install-apache2-module',
65
- 'passenger-install-nginx-module'
66
- ]
57
+ # Used during native packaging. Specifies executables for
58
+ # which the shebang should NOT be set to #!/usr/bin/ruby,
59
+ # so that these executables can be run with any Ruby interpreter
60
+ # the user desires.
61
+ EXECUTABLES_WITH_FREE_RUBY = [
62
+ 'passenger',
63
+ 'passenger-config',
64
+ 'passenger-install-apache2-module',
65
+ 'passenger-install-nginx-module'
66
+ ]
67
67
 
68
- # A list of globs which match all files that should be packaged
69
- # in the Phusion Passenger gem or tarball.
70
- GLOB = [
71
- '.gitignore',
72
- '.travis.yml',
73
- '.editorconfig',
74
- 'configure',
75
- 'Rakefile',
76
- 'Gemfile',
77
- 'Gemfile.lock',
78
- 'Vagrantfile',
79
- 'README.md',
80
- 'CONTRIBUTORS',
81
- 'CONTRIBUTING.md',
82
- 'LICENSE',
83
- 'CHANGELOG',
84
- 'INSTALL.md',
85
- 'NEWS',
86
- 'package.json',
87
- 'npm-shrinkwrap.json',
88
- 'passenger.gemspec',
89
- 'build/*.rb',
90
- 'lib/*.rb',
91
- 'lib/**/*.rb',
92
- 'lib/**/*.py',
93
- 'node_lib/**/*.js',
94
- 'bin/*',
95
- 'doc/**/*',
96
- 'man/*',
97
- 'debian.template/**/*',
98
- 'packaging/**/*',
99
- 'helper-scripts/**/*',
100
- 'ext/common/**/*.{cpp,c,h,hpp,md,erb}',
101
- 'ext/apache2/*.{cpp,h,hpp,c,erb}',
102
- 'ext/nginx/*.{c,cpp,h,erb}',
103
- 'ext/nginx/config',
104
- 'ext/boost/**/*',
105
- 'ext/libev/{LICENSE,Changes,README,Makefile.am,Makefile.in}',
106
- 'ext/libev/{*.m4,autogen.sh,config.guess,config.h.in,config.sub}',
107
- 'ext/libev/{configure,configure.ac,depcomp,install-sh,ltmain.sh,missing,mkinstalldirs}',
108
- 'ext/libev/{*.h,*.c}',
109
- 'ext/libeio/{LICENSE,Changes,README,Makefile.am,Makefile.in}',
110
- 'ext/libeio/{*.m4,autogen.sh,config.guess,config.h.in,config.sub}',
111
- 'ext/libeio/{configure,configure.ac,install-sh,ltmain.sh,missing,mkinstalldirs}',
112
- 'ext/libeio/{*.h,*.c}',
113
- 'ext/oxt/*.hpp',
114
- 'ext/oxt/*.cpp',
115
- 'ext/oxt/*.txt',
116
- 'ext/oxt/detail/*.hpp',
117
- 'ext/ruby/*.{c,rb}',
118
- 'dev/**/*',
119
- 'resources/**/*',
120
- 'test/.rspec',
121
- 'test/*.example',
122
- 'test/*.travis',
123
- 'test/*.rpm-automation',
124
- 'test/*.vagrant',
125
- 'test/*.supp',
126
- 'test/support/*.{c,cpp,h,rb}',
127
- 'test/tut/*',
128
- 'test/cxx/**/*.{cpp,h}',
129
- 'test/oxt/*.{cpp,hpp}',
130
- 'test/ruby/**/*',
131
- 'test/node/**/*',
132
- 'test/integration_tests/**/*',
133
- 'test/stub/**/*',
134
- 'test/stub/**/.*'
135
- ]
68
+ # A list of globs which match all files that should be packaged
69
+ # in the Phusion Passenger gem or tarball.
70
+ GLOB = [
71
+ '.gitignore',
72
+ '.travis.yml',
73
+ '.editorconfig',
74
+ 'configure',
75
+ 'Rakefile',
76
+ 'Gemfile',
77
+ 'Gemfile.lock',
78
+ 'Vagrantfile',
79
+ 'README.md',
80
+ 'CONTRIBUTORS',
81
+ 'CONTRIBUTING.md',
82
+ 'LICENSE',
83
+ 'CHANGELOG',
84
+ 'INSTALL.md',
85
+ 'NEWS',
86
+ 'package.json',
87
+ 'npm-shrinkwrap.json',
88
+ 'passenger.gemspec',
89
+ 'build/*.rb',
90
+ 'lib/*.rb',
91
+ 'lib/**/*.rb',
92
+ 'lib/**/*.py',
93
+ 'node_lib/**/*.js',
94
+ 'bin/*',
95
+ 'doc/**/*',
96
+ 'man/*',
97
+ 'debian.template/**/*',
98
+ 'packaging/**/*',
99
+ 'helper-scripts/**/*',
100
+ 'ext/common/**/*.{cpp,c,h,hpp,md,erb}',
101
+ 'ext/apache2/*.{cpp,h,hpp,c,erb}',
102
+ 'ext/nginx/*.{c,cpp,h,erb}',
103
+ 'ext/nginx/config',
104
+ 'ext/boost/**/*',
105
+ 'ext/libev/{LICENSE,Changes,README,Makefile.am,Makefile.in}',
106
+ 'ext/libev/{*.m4,autogen.sh,config.guess,config.h.in,config.sub}',
107
+ 'ext/libev/{configure,configure.ac,depcomp,install-sh,ltmain.sh,missing,mkinstalldirs}',
108
+ 'ext/libev/{*.h,*.c}',
109
+ 'ext/libeio/{LICENSE,Changes,README,Makefile.am,Makefile.in}',
110
+ 'ext/libeio/{*.m4,autogen.sh,config.guess,config.h.in,config.sub}',
111
+ 'ext/libeio/{configure,configure.ac,install-sh,ltmain.sh,missing,mkinstalldirs}',
112
+ 'ext/libeio/{*.h,*.c}',
113
+ 'ext/oxt/*.hpp',
114
+ 'ext/oxt/*.cpp',
115
+ 'ext/oxt/*.txt',
116
+ 'ext/oxt/detail/*.hpp',
117
+ 'ext/ruby/*.{c,rb}',
118
+ 'dev/**/*',
119
+ 'resources/**/*',
120
+ 'test/.rspec',
121
+ 'test/*.example',
122
+ 'test/*.travis',
123
+ 'test/*.rpm-automation',
124
+ 'test/*.vagrant',
125
+ 'test/*.supp',
126
+ 'test/support/*.{c,cpp,h,rb}',
127
+ 'test/tut/*',
128
+ 'test/cxx/**/*.{cpp,h}',
129
+ 'test/oxt/*.{cpp,hpp}',
130
+ 'test/ruby/**/*',
131
+ 'test/node/**/*',
132
+ 'test/integration_tests/**/*',
133
+ 'test/stub/**/*',
134
+ 'test/stub/**/.*'
135
+ ]
136
136
 
137
- EXCLUDE_GLOB = [
138
- '**/.DS_Store',
139
- 'packaging/*/.git',
140
- 'test/stub/rails_apps/3.0/empty/help/**/*',
141
- 'test/stub/*.dSYM'
142
- ]
137
+ EXCLUDE_GLOB = [
138
+ '**/.DS_Store',
139
+ 'packaging/*/.git',
140
+ 'test/stub/rails_apps/3.0/empty/help/**/*',
141
+ 'test/stub/*.dSYM'
142
+ ]
143
143
 
144
- # Files that should be excluded from the Debian tarball.
145
- DEBIAN_EXCLUDE_GLOB = [
146
- "debian.template/**/*",
147
- "packaging/**/*",
148
- ]
144
+ # Files that should be excluded from the Debian tarball.
145
+ DEBIAN_EXCLUDE_GLOB = [
146
+ "debian.template/**/*",
147
+ "packaging/**/*",
148
+ ]
149
149
 
150
- # Files and directories that should be excluded from the Homebrew installation.
151
- HOMEBREW_EXCLUDE = [
152
- ".gitignore", ".gitmodules", ".travis.yml", "package.json", "Vagrantfile",
153
- "npm-shrinkwrap.json", "Gemfile", "Gemfile.lock", "debian.template",
154
- "packaging", "dev", "test"
155
- ]
150
+ # Files and directories that should be excluded from the Homebrew installation.
151
+ HOMEBREW_EXCLUDE = [
152
+ ".gitignore", ".gitmodules", ".travis.yml", "package.json", "Vagrantfile",
153
+ "npm-shrinkwrap.json", "Gemfile", "Gemfile.lock", "debian.template",
154
+ "packaging", "dev", "test"
155
+ ]
156
156
 
157
- def self.files
158
- result = Dir[*GLOB] - Dir[*EXCLUDE_GLOB]
159
- result.reject! { |path| path =~ %r{/\.\.?$} }
160
- return result
161
- end
157
+ def self.files
158
+ result = Dir[*GLOB] - Dir[*EXCLUDE_GLOB]
159
+ result.reject! { |path| path =~ %r{/\.\.?$} }
160
+ return result
161
+ end
162
162
 
163
- def self.debian_orig_tarball_files
164
- return files - Dir[*DEBIAN_EXCLUDE_GLOB]
165
- end
166
- end
163
+ def self.debian_orig_tarball_files
164
+ return files - Dir[*DEBIAN_EXCLUDE_GLOB]
165
+ end
166
+ end
167
167
 
168
168
  end # module PhusionPassenger
@@ -26,365 +26,365 @@ PhusionPassenger.require_passenger_lib 'utils/tmpio'
26
26
 
27
27
  module PhusionPassenger
28
28
 
29
- # This module autodetects various platform-specific information, and
30
- # provides that information through constants.
31
- module PlatformInfo
32
- private
33
- @@cache_dir = nil
34
- @@verbose = ['1', 'true', 'on', 'yes'].include?(ENV['VERBOSE'])
35
- @@log_implementation = lambda do |message|
36
- message = reindent(message, 3)
37
- message.sub!(/^ /, '')
38
- STDERR.puts " * #{message}"
39
- end
40
-
41
- def self.private_class_method(name)
42
- metaclass = class << self; self; end
43
- metaclass.send(:private, name)
44
- end
45
- private_class_method :private_class_method
46
-
47
- # Turn the specified class method into a memoized one. If the given
48
- # class method is called without arguments, then its result will be
49
- # memoized, frozen, and returned upon subsequent calls without arguments.
50
- # Calls with arguments are never memoized.
51
- #
52
- # If +cache_to_disk+ is true and a cache directory has been set with
53
- # <tt>PlatformInfo.cache_dir=</tt> then result is cached to a file on disk,
54
- # so that memoized results persist over multiple process runs. This
55
- # cache file expires in +cache_time+ seconds (1 hour by default) after
56
- # it has been written.
57
- #
58
- # def self.foo(max = 10)
59
- # rand(max)
60
- # end
61
- # memoize :foo
62
- #
63
- # foo # => 3
64
- # foo # => 3
65
- # foo(100) # => 49
66
- # foo(100) # => 26
67
- # foo # => 3
68
- def self.memoize(method, cache_to_disk = false, cache_time = 3600)
69
- # We use class_eval here because Ruby 1.8.5 doesn't support class_variable_get/set.
70
- metaclass = class << self; self; end
71
- metaclass.send(:alias_method, "_unmemoized_#{method}", method)
72
- variable_name = "@@memoized_#{method}".sub(/\?/, '')
73
- check_variable_name = "@@has_memoized_#{method}".sub(/\?/, '')
74
- eval(%Q{
75
- #{variable_name} = nil
76
- #{check_variable_name} = false
77
- })
78
- line = __LINE__ + 1
79
- source = %Q{
80
- def self.#{method}(*args) # def self.httpd(*args)
81
- if args.empty? # if args.empty?
82
- if !#{check_variable_name} # if !@@has_memoized_httpd
83
- if @@cache_dir # if @@cache_dir
84
- cache_file = File.join(@@cache_dir, "#{method}") # cache_file = File.join(@@cache_dir, "httpd")
85
- end # end
86
- read_from_cache_file = false # read_from_cache_file = false
87
- if #{cache_to_disk} && cache_file && File.exist?(cache_file) # if #{cache_to_disk} && File.exist?(cache_file)
88
- cache_file_stat = File.stat(cache_file) # cache_file_stat = File.stat(cache_file)
89
- read_from_cache_file = # read_from_cache_file =
90
- Time.now - cache_file_stat.mtime < #{cache_time} # Time.now - cache_file_stat.mtime < #{cache_time}
91
- end # end
92
- if read_from_cache_file # if read_from_cache_file
93
- data = File.read(cache_file) # data = File.read(cache_file)
94
- #{variable_name} = Marshal.load(data).freeze # @@memoized_httpd = Marshal.load(data).freeze
95
- #{check_variable_name} = true # @@has_memoized_httpd = true
96
- else # else
97
- #{variable_name} = _unmemoized_#{method}.freeze # @@memoized_httpd = _unmemoized_httpd.freeze
98
- #{check_variable_name} = true # @@has_memoized_httpd = true
99
- if cache_file && #{cache_to_disk} # if cache_file && #{cache_to_disk}
100
- begin # begin
101
- if !File.directory?(@@cache_dir) # if !File.directory?(@@cache_dir)
102
- Dir.mkdir(@@cache_dir) # Dir.mkdir(@@cache_dir)
103
- end # end
104
- File.open(cache_file, "wb") do |f| # File.open(cache_file, "wb") do |f|
105
- f.write(Marshal.dump(#{variable_name})) # f.write(Marshal.dump(@@memoized_httpd))
106
- end # end
107
- rescue Errno::EACCES # rescue Errno::EACCES
108
- # Ignore permission error. # # Ignore permission error.
109
- end # end
110
- end # end
111
- end # end
112
- end # end
113
- #{variable_name} # @@memoized_httpd
114
- else # else
115
- _unmemoized_#{method}(*args) # _unmemoized_httpd(*args)
116
- end # end
117
- end # end
118
- }
119
- class_eval(source, __FILE__, line)
120
- end
121
- private_class_method :memoize
122
-
123
- # Look in the directory +dir+ and check whether there's an executable
124
- # whose base name is equal to one of the elements in +possible_names+.
125
- # If so, returns the full filename. If not, returns nil.
126
- def self.select_executable(dir, *possible_names)
127
- possible_names.each do |name|
128
- filename = "#{dir}/#{name}"
129
- if File.file?(filename) && File.executable?(filename)
130
- return filename
131
- end
132
- end
133
- return nil
134
- end
135
- private_class_method :select_executable
136
-
137
- def self.unindent(str)
138
- str = str.dup
139
- str.gsub!(/\A([\s\t]*\n)+/, '')
140
- str.gsub!(/[\s\t\n]+\Z/, '')
141
- indent = str.split("\n").select{ |line| !line.strip.empty? }.map{ |line| line.index(/[^\s]/) }.compact.min || 0
142
- str.gsub!(/^[[:blank:]]{#{indent}}/, '')
143
- return str
144
- end
145
- private_class_method :unindent
146
-
147
- def self.reindent(str, level)
148
- str = unindent(str)
149
- str.gsub!(/^/, ' ' * level)
150
- return str
151
- end
152
- private_class_method :reindent
153
-
154
- def self.create_temp_file(name, dir = tmpdir)
155
- # This function is mostly used for compiling C programs to autodetect
156
- # system properties. We create a secure temp subdirectory to prevent
157
- # TOCTU attacks, especially because we don't know how the compiler
158
- # handles this.
159
- PhusionPassenger::Utils.mktmpdir("passenger.", dir) do |subdir|
160
- filename = "#{subdir}/#{name}"
161
- f = File.open(filename, "w")
162
- begin
163
- yield(filename, f)
164
- ensure
165
- f.close if !f.closed?
166
- end
167
- end
168
- end
169
- private_class_method :create_temp_file
170
-
171
- def self.log(message)
172
- if verbose?
173
- @@log_implementation.call(message)
174
- end
175
- end
176
- private_class_method :log
177
-
178
- public
179
- class RuntimeError < ::RuntimeError
180
- end
181
-
182
-
183
- def self.cache_dir=(value)
184
- @@cache_dir = value
185
- end
186
-
187
- def self.cache_dir
188
- return @@cache_dir
189
- end
190
-
191
- def self.verbose=(val)
192
- @@verbose = val
193
- end
194
-
195
- def self.verbose?
196
- return @@verbose
197
- end
198
-
199
- def self.log_implementation=(impl)
200
- @@log_implementation = impl
201
- end
202
-
203
- def self.log_implementation
204
- return @@log_implementation
205
- end
206
-
207
-
208
- def self.env_defined?(name)
209
- return !ENV[name].nil? && !ENV[name].empty?
210
- end
211
-
212
- def self.string_env(name, default_value = nil)
213
- value = ENV[name]
214
- if value.nil? || value.empty?
215
- return default_value
216
- else
217
- return value
218
- end
219
- end
220
-
221
- def self.read_file(filename)
222
- return File.open(filename, "rb") do |f|
223
- f.read
224
- end
225
- rescue
226
- return ""
227
- end
228
-
229
- def self.tmpdir
230
- result = ENV['TMPDIR']
231
- if result && !result.empty?
232
- return result.sub(/\/+\Z/, '')
233
- else
234
- return '/tmp'
235
- end
236
- end
237
- memoize :tmpdir
238
-
239
- # Returns the directory in which test executables should be placed. The
240
- # returned directory is guaranteed to be writable and guaranteed to
241
- # not be mounted with the 'noexec' option.
242
- # If no such directory can be found then it will raise a PlatformInfo::RuntimeError
243
- # with an appropriate error message.
244
- def self.tmpexedir
245
- basename = "test-exe.#{Process.pid}.#{Thread.current.object_id}"
246
- attempts = []
247
-
248
- dir = tmpdir
249
- filename = "#{dir}/#{basename}"
250
- begin
251
- File.open(filename, 'w') do |f|
252
- f.puts("#!/bin/sh")
253
- end
254
- File.chmod(0700, filename)
255
- if system(filename)
256
- return dir
257
- else
258
- attempts << { :dir => dir,
259
- :error => "This directory's filesystem is mounted with the 'noexec' option." }
260
- end
261
- rescue Errno::ENOENT
262
- attempts << { :dir => dir, :error => "This directory doesn't exist." }
263
- rescue Errno::EACCES
264
- attempts << { :dir => dir, :error => "This program doesn't have permission to write to this directory." }
265
- rescue SystemCallError => e
266
- attempts << { :dir => dir, :error => e.message }
267
- ensure
268
- File.unlink(filename) rescue nil
269
- end
270
-
271
- dir = Dir.pwd
272
- filename = "#{dir}/#{basename}"
273
- begin
274
- File.open(filename, 'w') do |f|
275
- f.puts("#!/bin/sh")
276
- end
277
- File.chmod(0700, filename)
278
- if system(filename)
279
- return dir
280
- else
281
- attempts << { :dir => dir,
282
- :error => "This directory's filesystem is mounted with the 'noexec' option." }
283
- end
284
- rescue Errno::ENOENT
285
- attempts << { :dir => dir, :error => "This directory doesn't exist." }
286
- rescue Errno::EACCES
287
- attempts << { :dir => dir, :error => "This program doesn't have permission to write to this directory." }
288
- rescue SystemCallError => e
289
- attempts << { :dir => dir, :error => e.message }
290
- ensure
291
- File.unlink(filename) rescue nil
292
- end
293
-
294
- message = "ERROR: Cannot find suitable temporary directory\n" +
295
- "In order to run certain tests, this program " +
296
- "must be able to write temporary\n" +
297
- "executable files to some directory. However no such " +
298
- "directory can be found. \n" +
299
- "The following directories have been tried:\n\n"
300
- attempts.each do |attempt|
301
- message << " * #{attempt[:dir]}\n"
302
- message << " #{attempt[:error]}\n"
303
- end
304
- message << "\nYou can solve this problem by telling this program what directory to write\n" <<
305
- "temporary executable files to, as follows:\n" <<
306
- "\n" <<
307
- " Set the $TMPDIR environment variable to the desired directory's filename and\n" <<
308
- " re-run this program.\n" <<
309
- "\n" <<
310
- "Notes:\n" <<
311
- "\n" <<
312
- " * If you're using 'sudo'/'rvmsudo', remember that 'sudo'/'rvmsudo' unsets all\n" <<
313
- " environment variables, so you must set the environment variable *after*\n" <<
314
- " having gained root privileges.\n" <<
315
- " * The directory you choose must writeable and must not be mounted with the\n" <<
316
- " 'noexec' option."
317
- raise RuntimeError, message
318
- end
319
- memoize :tmpexedir
320
-
321
- def self.rb_config
322
- if defined?(::RbConfig)
323
- return ::RbConfig::CONFIG
324
- else
325
- return ::Config::CONFIG
326
- end
327
- end
328
-
329
- # Check whether the specified command is in $PATH, and return its
330
- # absolute filename. Returns nil if the command is not found.
331
- #
332
- # This function exists because system('which') doesn't always behave
333
- # correctly, for some weird reason.
334
- #
335
- # When `is_executable` is true, this function checks whether
336
- # there is an executable named `name` in $PATH. When false, it
337
- # assumes that `name` is not an executable name but a command string
338
- # (e.g. "ccache gcc"). It then infers the executable name ("ccache")
339
- # from the command string, and checks for that instead.
340
- def self.find_command(name, is_executable = true)
341
- name = name.to_s
342
- if !is_executable && name =~ / /
343
- name = name.sub(/ .*/, '')
344
- end
345
- if name =~ /^\//
346
- if File.executable?(name)
347
- return name
348
- else
349
- return nil
350
- end
351
- else
352
- ENV['PATH'].to_s.split(File::PATH_SEPARATOR).each do |directory|
353
- next if directory.empty?
354
- path = File.join(directory, name)
355
- if File.file?(path) && File.executable?(path)
356
- return path
357
- end
358
- end
359
- return nil
360
- end
361
- end
362
-
363
- def self.find_all_commands(name)
364
- search_dirs = ENV['PATH'].to_s.split(File::PATH_SEPARATOR)
365
- search_dirs.concat(%w(/bin /sbin /usr/bin /usr/sbin /usr/local/bin /usr/local/sbin))
366
- ["/opt/*/bin", "/opt/*/sbin", "/usr/local/*/bin", "/usr/local/*/sbin"].each do |glob|
367
- search_dirs.concat(Dir[glob])
368
- end
369
- search_dirs.delete("")
370
- search_dirs.uniq!
371
-
372
- result = []
373
- search_dirs.each do |directory|
374
- path = File.join(directory, name)
375
- if !File.exist?(path)
376
- log "Looking for #{path}: not found"
377
- elsif !File.file?(path)
378
- log "Looking for #{path}: found, but is not a file"
379
- elsif !File.executable?(path)
380
- log "Looking for #{path}: found, but is not executable"
381
- else
382
- log "Looking for #{path}: found"
383
- result << path
384
- end
385
- end
386
- return result
387
- end
388
- end
29
+ # This module autodetects various platform-specific information, and
30
+ # provides that information through constants.
31
+ module PlatformInfo
32
+ private
33
+ @@cache_dir = nil
34
+ @@verbose = ['1', 'true', 'on', 'yes'].include?(ENV['VERBOSE'])
35
+ @@log_implementation = lambda do |message|
36
+ message = reindent(message, 3)
37
+ message.sub!(/^ /, '')
38
+ STDERR.puts " * #{message}"
39
+ end
40
+
41
+ def self.private_class_method(name)
42
+ metaclass = class << self; self; end
43
+ metaclass.send(:private, name)
44
+ end
45
+ private_class_method :private_class_method
46
+
47
+ # Turn the specified class method into a memoized one. If the given
48
+ # class method is called without arguments, then its result will be
49
+ # memoized, frozen, and returned upon subsequent calls without arguments.
50
+ # Calls with arguments are never memoized.
51
+ #
52
+ # If +cache_to_disk+ is true and a cache directory has been set with
53
+ # <tt>PlatformInfo.cache_dir=</tt> then result is cached to a file on disk,
54
+ # so that memoized results persist over multiple process runs. This
55
+ # cache file expires in +cache_time+ seconds (1 hour by default) after
56
+ # it has been written.
57
+ #
58
+ # def self.foo(max = 10)
59
+ # rand(max)
60
+ # end
61
+ # memoize :foo
62
+ #
63
+ # foo # => 3
64
+ # foo # => 3
65
+ # foo(100) # => 49
66
+ # foo(100) # => 26
67
+ # foo # => 3
68
+ def self.memoize(method, cache_to_disk = false, cache_time = 3600)
69
+ # We use class_eval here because Ruby 1.8.5 doesn't support class_variable_get/set.
70
+ metaclass = class << self; self; end
71
+ metaclass.send(:alias_method, "_unmemoized_#{method}", method)
72
+ variable_name = "@@memoized_#{method}".sub(/\?/, '')
73
+ check_variable_name = "@@has_memoized_#{method}".sub(/\?/, '')
74
+ eval(%Q{
75
+ #{variable_name} = nil
76
+ #{check_variable_name} = false
77
+ })
78
+ line = __LINE__ + 1
79
+ source = %Q{
80
+ def self.#{method}(*args) # def self.httpd(*args)
81
+ if args.empty? # if args.empty?
82
+ if !#{check_variable_name} # if !@@has_memoized_httpd
83
+ if @@cache_dir # if @@cache_dir
84
+ cache_file = File.join(@@cache_dir, "#{method}") # cache_file = File.join(@@cache_dir, "httpd")
85
+ end # end
86
+ read_from_cache_file = false # read_from_cache_file = false
87
+ if #{cache_to_disk} && cache_file && File.exist?(cache_file) # if #{cache_to_disk} && File.exist?(cache_file)
88
+ cache_file_stat = File.stat(cache_file) # cache_file_stat = File.stat(cache_file)
89
+ read_from_cache_file = # read_from_cache_file =
90
+ Time.now - cache_file_stat.mtime < #{cache_time} # Time.now - cache_file_stat.mtime < #{cache_time}
91
+ end # end
92
+ if read_from_cache_file # if read_from_cache_file
93
+ data = File.read(cache_file) # data = File.read(cache_file)
94
+ #{variable_name} = Marshal.load(data).freeze # @@memoized_httpd = Marshal.load(data).freeze
95
+ #{check_variable_name} = true # @@has_memoized_httpd = true
96
+ else # else
97
+ #{variable_name} = _unmemoized_#{method}.freeze # @@memoized_httpd = _unmemoized_httpd.freeze
98
+ #{check_variable_name} = true # @@has_memoized_httpd = true
99
+ if cache_file && #{cache_to_disk} # if cache_file && #{cache_to_disk}
100
+ begin # begin
101
+ if !File.directory?(@@cache_dir) # if !File.directory?(@@cache_dir)
102
+ Dir.mkdir(@@cache_dir) # Dir.mkdir(@@cache_dir)
103
+ end # end
104
+ File.open(cache_file, "wb") do |f| # File.open(cache_file, "wb") do |f|
105
+ f.write(Marshal.dump(#{variable_name})) # f.write(Marshal.dump(@@memoized_httpd))
106
+ end # end
107
+ rescue Errno::EACCES # rescue Errno::EACCES
108
+ # Ignore permission error. # # Ignore permission error.
109
+ end # end
110
+ end # end
111
+ end # end
112
+ end # end
113
+ #{variable_name} # @@memoized_httpd
114
+ else # else
115
+ _unmemoized_#{method}(*args) # _unmemoized_httpd(*args)
116
+ end # end
117
+ end # end
118
+ }
119
+ class_eval(source, __FILE__, line)
120
+ end
121
+ private_class_method :memoize
122
+
123
+ # Look in the directory +dir+ and check whether there's an executable
124
+ # whose base name is equal to one of the elements in +possible_names+.
125
+ # If so, returns the full filename. If not, returns nil.
126
+ def self.select_executable(dir, *possible_names)
127
+ possible_names.each do |name|
128
+ filename = "#{dir}/#{name}"
129
+ if File.file?(filename) && File.executable?(filename)
130
+ return filename
131
+ end
132
+ end
133
+ return nil
134
+ end
135
+ private_class_method :select_executable
136
+
137
+ def self.unindent(str)
138
+ str = str.dup
139
+ str.gsub!(/\A([\s\t]*\n)+/, '')
140
+ str.gsub!(/[\s\t\n]+\Z/, '')
141
+ indent = str.split("\n").select{ |line| !line.strip.empty? }.map{ |line| line.index(/[^\s]/) }.compact.min || 0
142
+ str.gsub!(/^[[:blank:]]{#{indent}}/, '')
143
+ return str
144
+ end
145
+ private_class_method :unindent
146
+
147
+ def self.reindent(str, level)
148
+ str = unindent(str)
149
+ str.gsub!(/^/, ' ' * level)
150
+ return str
151
+ end
152
+ private_class_method :reindent
153
+
154
+ def self.create_temp_file(name, dir = tmpdir)
155
+ # This function is mostly used for compiling C programs to autodetect
156
+ # system properties. We create a secure temp subdirectory to prevent
157
+ # TOCTU attacks, especially because we don't know how the compiler
158
+ # handles this.
159
+ PhusionPassenger::Utils.mktmpdir("passenger.", dir) do |subdir|
160
+ filename = "#{subdir}/#{name}"
161
+ f = File.open(filename, "w")
162
+ begin
163
+ yield(filename, f)
164
+ ensure
165
+ f.close if !f.closed?
166
+ end
167
+ end
168
+ end
169
+ private_class_method :create_temp_file
170
+
171
+ def self.log(message)
172
+ if verbose?
173
+ @@log_implementation.call(message)
174
+ end
175
+ end
176
+ private_class_method :log
177
+
178
+ public
179
+ class RuntimeError < ::RuntimeError
180
+ end
181
+
182
+
183
+ def self.cache_dir=(value)
184
+ @@cache_dir = value
185
+ end
186
+
187
+ def self.cache_dir
188
+ return @@cache_dir
189
+ end
190
+
191
+ def self.verbose=(val)
192
+ @@verbose = val
193
+ end
194
+
195
+ def self.verbose?
196
+ return @@verbose
197
+ end
198
+
199
+ def self.log_implementation=(impl)
200
+ @@log_implementation = impl
201
+ end
202
+
203
+ def self.log_implementation
204
+ return @@log_implementation
205
+ end
206
+
207
+
208
+ def self.env_defined?(name)
209
+ return !ENV[name].nil? && !ENV[name].empty?
210
+ end
211
+
212
+ def self.string_env(name, default_value = nil)
213
+ value = ENV[name]
214
+ if value.nil? || value.empty?
215
+ return default_value
216
+ else
217
+ return value
218
+ end
219
+ end
220
+
221
+ def self.read_file(filename)
222
+ return File.open(filename, "rb") do |f|
223
+ f.read
224
+ end
225
+ rescue
226
+ return ""
227
+ end
228
+
229
+ def self.tmpdir
230
+ result = ENV['TMPDIR']
231
+ if result && !result.empty?
232
+ return result.sub(/\/+\Z/, '')
233
+ else
234
+ return '/tmp'
235
+ end
236
+ end
237
+ memoize :tmpdir
238
+
239
+ # Returns the directory in which test executables should be placed. The
240
+ # returned directory is guaranteed to be writable and guaranteed to
241
+ # not be mounted with the 'noexec' option.
242
+ # If no such directory can be found then it will raise a PlatformInfo::RuntimeError
243
+ # with an appropriate error message.
244
+ def self.tmpexedir
245
+ basename = "test-exe.#{Process.pid}.#{Thread.current.object_id}"
246
+ attempts = []
247
+
248
+ dir = tmpdir
249
+ filename = "#{dir}/#{basename}"
250
+ begin
251
+ File.open(filename, 'w') do |f|
252
+ f.puts("#!/bin/sh")
253
+ end
254
+ File.chmod(0700, filename)
255
+ if system(filename)
256
+ return dir
257
+ else
258
+ attempts << { :dir => dir,
259
+ :error => "This directory's filesystem is mounted with the 'noexec' option." }
260
+ end
261
+ rescue Errno::ENOENT
262
+ attempts << { :dir => dir, :error => "This directory doesn't exist." }
263
+ rescue Errno::EACCES
264
+ attempts << { :dir => dir, :error => "This program doesn't have permission to write to this directory." }
265
+ rescue SystemCallError => e
266
+ attempts << { :dir => dir, :error => e.message }
267
+ ensure
268
+ File.unlink(filename) rescue nil
269
+ end
270
+
271
+ dir = Dir.pwd
272
+ filename = "#{dir}/#{basename}"
273
+ begin
274
+ File.open(filename, 'w') do |f|
275
+ f.puts("#!/bin/sh")
276
+ end
277
+ File.chmod(0700, filename)
278
+ if system(filename)
279
+ return dir
280
+ else
281
+ attempts << { :dir => dir,
282
+ :error => "This directory's filesystem is mounted with the 'noexec' option." }
283
+ end
284
+ rescue Errno::ENOENT
285
+ attempts << { :dir => dir, :error => "This directory doesn't exist." }
286
+ rescue Errno::EACCES
287
+ attempts << { :dir => dir, :error => "This program doesn't have permission to write to this directory." }
288
+ rescue SystemCallError => e
289
+ attempts << { :dir => dir, :error => e.message }
290
+ ensure
291
+ File.unlink(filename) rescue nil
292
+ end
293
+
294
+ message = "ERROR: Cannot find suitable temporary directory\n" +
295
+ "In order to run certain tests, this program " +
296
+ "must be able to write temporary\n" +
297
+ "executable files to some directory. However no such " +
298
+ "directory can be found. \n" +
299
+ "The following directories have been tried:\n\n"
300
+ attempts.each do |attempt|
301
+ message << " * #{attempt[:dir]}\n"
302
+ message << " #{attempt[:error]}\n"
303
+ end
304
+ message << "\nYou can solve this problem by telling this program what directory to write\n" <<
305
+ "temporary executable files to, as follows:\n" <<
306
+ "\n" <<
307
+ " Set the $TMPDIR environment variable to the desired directory's filename and\n" <<
308
+ " re-run this program.\n" <<
309
+ "\n" <<
310
+ "Notes:\n" <<
311
+ "\n" <<
312
+ " * If you're using 'sudo'/'rvmsudo', remember that 'sudo'/'rvmsudo' unsets all\n" <<
313
+ " environment variables, so you must set the environment variable *after*\n" <<
314
+ " having gained root privileges.\n" <<
315
+ " * The directory you choose must writeable and must not be mounted with the\n" <<
316
+ " 'noexec' option."
317
+ raise RuntimeError, message
318
+ end
319
+ memoize :tmpexedir
320
+
321
+ def self.rb_config
322
+ if defined?(::RbConfig)
323
+ return ::RbConfig::CONFIG
324
+ else
325
+ return ::Config::CONFIG
326
+ end
327
+ end
328
+
329
+ # Check whether the specified command is in $PATH, and return its
330
+ # absolute filename. Returns nil if the command is not found.
331
+ #
332
+ # This function exists because system('which') doesn't always behave
333
+ # correctly, for some weird reason.
334
+ #
335
+ # When `is_executable` is true, this function checks whether
336
+ # there is an executable named `name` in $PATH. When false, it
337
+ # assumes that `name` is not an executable name but a command string
338
+ # (e.g. "ccache gcc"). It then infers the executable name ("ccache")
339
+ # from the command string, and checks for that instead.
340
+ def self.find_command(name, is_executable = true)
341
+ name = name.to_s
342
+ if !is_executable && name =~ / /
343
+ name = name.sub(/ .*/, '')
344
+ end
345
+ if name =~ /^\//
346
+ if File.executable?(name)
347
+ return name
348
+ else
349
+ return nil
350
+ end
351
+ else
352
+ ENV['PATH'].to_s.split(File::PATH_SEPARATOR).each do |directory|
353
+ next if directory.empty?
354
+ path = File.join(directory, name)
355
+ if File.file?(path) && File.executable?(path)
356
+ return path
357
+ end
358
+ end
359
+ return nil
360
+ end
361
+ end
362
+
363
+ def self.find_all_commands(name)
364
+ search_dirs = ENV['PATH'].to_s.split(File::PATH_SEPARATOR)
365
+ search_dirs.concat(%w(/bin /sbin /usr/bin /usr/sbin /usr/local/bin /usr/local/sbin))
366
+ ["/opt/*/bin", "/opt/*/sbin", "/usr/local/*/bin", "/usr/local/*/sbin"].each do |glob|
367
+ search_dirs.concat(Dir[glob])
368
+ end
369
+ search_dirs.delete("")
370
+ search_dirs.uniq!
371
+
372
+ result = []
373
+ search_dirs.each do |directory|
374
+ path = File.join(directory, name)
375
+ if !File.exist?(path)
376
+ log "Looking for #{path}: not found"
377
+ elsif !File.file?(path)
378
+ log "Looking for #{path}: found, but is not a file"
379
+ elsif !File.executable?(path)
380
+ log "Looking for #{path}: found, but is not executable"
381
+ else
382
+ log "Looking for #{path}: found"
383
+ result << path
384
+ end
385
+ end
386
+ return result
387
+ end
388
+ end
389
389
 
390
390
  end # module PhusionPassenger