passenger 4.0.46 → 4.0.48

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 CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- NTMzMjIwYzg3NGQxMTFmZDllM2ExZGU0MmUyM2E2MGFjODU0MDQyNQ==
4
+ Y2Q0N2U0NTcyNWY5ZWYwMDA3NzRmMGZjNzUwNGUzNTNhZGNiYzFmOA==
5
5
  data.tar.gz: !binary |-
6
- MTM5NmRmMWQyYzY0ZmZjNTNkMTYzYmFhZDcwZTVhNDdhZDI5YjM3MA==
6
+ N2NlN2NmMTRjYWU4NDAyN2Q2YWUxODJiNzJmOTA5M2Y5NWQ4YjUxMg==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- YmQ4Nzg3NTVjYzhhNDcyMzJkOWU0YTgwMmRiYzYwMGM4YzJlZDJiYjBlMDcw
10
- MzU3MGY2NTc4NWRlNTU4OGU1ODM3OTliNWQ4MWJhYWIyNzUxOGM3YWViMTM2
11
- NTQwYjE4NmIxYjczMTc4Y2I2YjliMjEwNGRmNTM0ZjkxY2EzMDc=
9
+ OTE2NzU1ODdmMDUyZWY0ZWUxNmMzYTZhMGY1ZTM2YTk1YzY3NjQyMGQzNzJh
10
+ ZTY0OWU4MzBlZGY1Y2RhZGM3NzViMTM3MzQzOWQxYjYzNDQ0ZTMyNWExYWYy
11
+ MzZhMGEwNzVlNjRjZjI2YzQ1ZTMyNGUyOTk4Mjc5MWNmMzI1YzQ=
12
12
  data.tar.gz: !binary |-
13
- MGNiMGE0ODZkYjlhZjdhYmI1YmJkYjJlN2M0YmY1MjkxZjg3OWQ5ZmEyNmE2
14
- NjhiY2RjZjRkZmRlZDdiMDg1MzI5YjI4M2JiNWQ2MDM3NDVkYTBjMmJlZTY3
15
- YzRhNmQyZDIwZjBkNzhmYTkyMTUxY2QyZjY5MWVhYmI3ODE0YjE=
13
+ ZjYyY2JmMWQ5NmViMTk3ZGVlNGY1NTMxMmZjMmU4OGQxMzk5ODc4NmYyMGE1
14
+ YTM5NDUxMjg2MmZkZWE4NjJjYzFiYmUxYWQzZWVlODNjNGQ2NDViOTM2OTMz
15
+ YWMzZjYxMzkzZTRkOGNlYTExYzgzNjQ1ZGZlZWUxZTkwYTU2NTE=
@@ -2,11 +2,11 @@
2
2
  Version: GnuPG/MacGPG2 v2.0.17 (Darwin)
3
3
  Comment: GPGTools - http://gpgtools.org
4
4
 
5
- iQEcBAABAgAGBQJTxCOxAAoJECrHRaUKISqMIQsH/3NGVBMEB/WcSyQeLVw8skQZ
6
- ZgD6xWOeNH7im6h44UwT7zebDNuVVE2vhPhxcuv5h5D3zKeSutLV9deGbvx2KRHF
7
- 5DhHC1M7YmirNDfxL1cD/mjHaK5XconhorcYghTwa9Co40c99pWB3DTMvt53zP4E
8
- udoJY26zO26PxpoZ3KQtkzp4PdTKs9VB3cq9YXuGtwjO10qUT/CJf2iXObYheSit
9
- zLC7b7L5qSDOg+Ty8PUQf3/vwyGp6X6+AlOcwJR8fHyWJ8TPn/xugAElUcHIsYDB
10
- jFb5rwDGYVmN6lpqVqVJ9+n4Ju2Sj9oBO4DCrPgTBvFXO0jfd8zK4JoCMb4H/2g=
11
- =EZq+
5
+ iQEcBAABAgAGBQJT0PH3AAoJECrHRaUKISqMFzYIAIzqK4Mt2VJ3+b5i9T+VXYdB
6
+ 3Rwh00XDqiOtDUoyDQCLFcB5WlyvcVSphhmk6QqPe5SQN17Ryuw8t0caWls/c+ZI
7
+ FjoTE9MNCG4MvRdwchquMiwmqqtq3RcWVLCBx/RHVOXwxGDEibTDqcVsW3nAgtvI
8
+ wP82mpi9pxmknv2Qer9d8SdNOhXTBKxhU8PJgEQAVeGskiB9Qs3IehGxulP/ZjJc
9
+ DUPhOVQpixapzU+ZmrQDY1UXn6yMV+z/sX/4icHgftm3O3t1cKg4cz0H3HPAkKK7
10
+ EOxsoyySfTXfcAI15NvLh26HdmVBD17wCBSgtUrS1BhexzfJHucdiKa7WUrikZg=
11
+ =KkS3
12
12
  -----END PGP SIGNATURE-----
data.tar.gz.asc CHANGED
@@ -2,11 +2,11 @@
2
2
  Version: GnuPG/MacGPG2 v2.0.17 (Darwin)
3
3
  Comment: GPGTools - http://gpgtools.org
4
4
 
5
- iQEcBAABAgAGBQJTxCOxAAoJECrHRaUKISqMCdsIAKR9HnGsLlsxmpu0zMWExqVb
6
- dHyyHP/ckMjqEsJs1jeS0iYniI59IxCLfcMCG0lYf0tLR1OSRbnTUSuDG7JQeKfN
7
- sA1OZ7i8UNPbFEhmzN/xAqmxioCNY0C85vPpUk4Vff11oLRmXN/YOKHKL0ukZIJs
8
- eaN9U+I+KtKCLkst5afwuzNlRMxDMxKnArdoWVD16iFbltMxHH+2l2wYF/APt4JS
9
- NAzBGbweQ8xi/7p1+ReVDG617Imh5aUt0tNEwlSbTS4P+fHObL4FaVPcVzzDGi17
10
- DxNCiqErNYCjEsy+6F4CjWPgO9fZ+IcwYqAk9NaW3z3ZrlQSK9F+hB+fiCalCRA=
11
- =BldL
5
+ iQEcBAABAgAGBQJT0PH2AAoJECrHRaUKISqMUYwH/0C1g6jcd/g4ux//vTqjoRFX
6
+ ShBZS3BXAeI0o2c4dq06mE8LM5FiIQmWa6mzRLooFgfUBzunC5TACyEQ65LaCi3r
7
+ 2QP07avW0JdSoCMypCld5EbTXacqfYRYtyVjnQRb9vbssFbHPVSnilL4m7N6Yit7
8
+ 2i/oDzaAaf8ka1fdfERXASwhyLuffn3IuVQz5L/zCd8HkcPyJpqmcd/oQ7jrdJng
9
+ EfoRsivoernTPBrhJqJB566DtkVPLEzd2TrBoO1UspENBpZzfAZChYdgJQscOavT
10
+ RPfX6B61kvahbpYfGU6A/bI8i7rOjKdGWIavaZex6ij32c+QQ+U2s3TdQBmtyIc=
11
+ =A4Gz
12
12
  -----END PGP SIGNATURE-----
data/CHANGELOG CHANGED
@@ -1,3 +1,24 @@
1
+ Release 4.0.48
2
+ --------------
3
+
4
+ * Fixed a race condition while determining what user an application should
5
+ be executed as. This bug could lead to applications being run as the wrong
6
+ user. Closes GH-1241.
7
+ * [Standalone] Improved autodetection of Rails asset pipeline files. This
8
+ prevents Standalone from incorrectly setting caching headers on non-asset
9
+ pipeline files. Closes GH-1225.
10
+ * Fixed compilation problems on CentOS 5. Thanks to J. Smith. Closes GH-1247.
11
+ * Fixed compilation problems on OpenBSD.
12
+ * Fixed compatibility with Ruby 1.8.5.
13
+
14
+
15
+ Release 4.0.47
16
+ --------------
17
+
18
+ * [Enterprise] Fixed a bug in Flying Passenger's `--max-preloader-idle-time`
19
+ option.
20
+
21
+
1
22
  Release 4.0.46
2
23
  --------------
3
24
 
@@ -34,7 +34,7 @@ require 'phusion_passenger'
34
34
 
35
35
  PhusionPassenger.locate_directories
36
36
 
37
- require 'digest'
37
+ require 'digest/sha2'
38
38
  require 'optparse'
39
39
  require 'fileutils'
40
40
  PhusionPassenger.require_passenger_lib 'platform_info/ruby'
@@ -268,7 +268,7 @@ private
268
268
  if download(url, tarball, DOWNLOAD_OPTION)
269
269
  Dir.chdir(@working_dir) do
270
270
  puts "<banner>Verifying PCRE checksum...</banner>"
271
- if Digest::SHA256.file(tarball) != PCRE_SHA256_CHECKSUM
271
+ if sha256_file(tarball) != PCRE_SHA256_CHECKSUM
272
272
  new_screen
273
273
  render_template "nginx/pcre_checksum_could_not_be_verified"
274
274
  wait
@@ -306,7 +306,7 @@ private
306
306
  if download(url, tarball, DOWNLOAD_OPTION)
307
307
  Dir.chdir(@working_dir) do
308
308
  puts "<banner>Verifying Nginx checksum...</banner>"
309
- if Digest::SHA256.file(tarball) != NGINX_SHA256_CHECKSUM
309
+ if sha256_file(tarball) != NGINX_SHA256_CHECKSUM
310
310
  return nil
311
311
  end
312
312
 
@@ -566,6 +566,20 @@ private
566
566
  end
567
567
  return @pcre_is_installed
568
568
  end
569
+
570
+ def sha256_file(path)
571
+ # We do this instead of using #file, for Ruby 1.8.5 support.
572
+ digest = Digest::SHA256.new
573
+ File.open(path, "rb") do |f|
574
+ buf = ''
575
+ buf.force_encoding('binary') if buf.respond_to?(:force_encoding)
576
+ while !f.eof?
577
+ f.read(1024 * 16, buf)
578
+ digest.update(buf)
579
+ end
580
+ end
581
+ return digest.hexdigest
582
+ end
569
583
  end
570
584
 
571
585
  ORIG_ARGV = ARGV.dup
@@ -1,5 +1,9 @@
1
1
  #!/usr/bin/env ruby
2
+ #
3
+ # Usage: ./dev/list_tests.rb <FILENAME>
4
+ #
2
5
  # Lists the test names in the given .cpp test file.
6
+
3
7
  require_relative '../lib/phusion_passenger/utils/ansi_colors'
4
8
 
5
9
  include PhusionPassenger::Utils::AnsiColors
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rake'
3
+
4
+ class RpmTool
5
+ include Rake::DSL
6
+
7
+ def initialize(argv)
8
+ @argv = argv.dup
9
+ end
10
+
11
+ def start
12
+ parse_options
13
+ end
14
+
15
+ private
16
+ def parse_options
17
+ sh "rake package:tarball"
18
+ end
19
+ end
20
+
21
+ RpmTool.new(ARGV).start
@@ -1,4 +1,6 @@
1
1
  #!/bin/bash
2
+ # This script is run by Travis, to execute tests in the CI environment.
3
+
2
4
  set -e
3
5
 
4
6
  export VERBOSE=1
data/dev/runner CHANGED
@@ -1,4 +1,10 @@
1
1
  #!/usr/bin/env ruby
2
+ #
3
+ # Usage: ./dev/runner <CODE>
4
+ #
5
+ # Evaluates Ruby code in an environment that has the Phusion Passenger
6
+ # libraries loaded.
7
+
2
8
  require File.expand_path(File.dirname(__FILE__) + "/../lib/phusion_passenger")
3
9
  PhusionPassenger.locate_directories
4
10
 
@@ -25,8 +25,10 @@
25
25
  #include <typeinfo>
26
26
  #include <algorithm>
27
27
  #include <utility>
28
+ #include <cstdio>
28
29
  #include <sstream>
29
30
  #include <limits.h>
31
+ #include <unistd.h>
30
32
  #include <boost/make_shared.hpp>
31
33
  #include <boost/date_time/posix_time/posix_time_types.hpp>
32
34
  #include <oxt/backtrace.hpp>
@@ -38,6 +40,7 @@
38
40
  #include <Exceptions.h>
39
41
  #include <MessageReadersWriters.h>
40
42
  #include <Utils.h>
43
+ #include <Utils/IOUtils.h>
41
44
  #include <Utils/ScopeGuard.h>
42
45
  #include <Utils/MessageIO.h>
43
46
  #include <Utils/JsonUtils.h>
@@ -184,7 +187,7 @@ void processAndLogNewSpawnException(SpawnException &e, const Options &options,
184
187
  UPDATE_TRACE_POINT();
185
188
  errorPage = renderer.renderWithDetails(appMessage, options, &e);
186
189
 
187
- #if defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__)
190
+ #if (defined(__linux__) && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 11))) || defined(__APPLE__) || defined(__FreeBSD__)
188
191
  snprintf(filename, PATH_MAX, "%s/passenger-error-XXXXXX.html",
189
192
  getSystemTempDir());
190
193
  fd = mkstemps(filename, sizeof(".html") - 1);
@@ -836,8 +836,21 @@ protected:
836
836
  void prepareUserSwitching(SpawnPreparationInfo &info, const Options &options) const {
837
837
  TRACE_POINT();
838
838
  if (geteuid() != 0) {
839
- struct passwd *userInfo = getpwuid(geteuid());
840
- if (userInfo == NULL) {
839
+ struct passwd pwd, *userInfo;
840
+ long bufSize;
841
+ shared_array<char> strings;
842
+
843
+ bufSize = sysconf(_SC_GETPW_R_SIZE_MAX);
844
+ if (bufSize == -1) {
845
+ // Let's hope this is enough.
846
+ bufSize = 1024 * 64;
847
+ }
848
+ strings.reset(new char[bufSize]);
849
+
850
+ userInfo = (struct passwd *) NULL;
851
+ if (getpwuid_r(geteuid(), &pwd, strings.get(), bufSize, &userInfo) != 0
852
+ || userInfo == (struct passwd *) NULL)
853
+ {
841
854
  throw RuntimeException("Cannot get user database entry for user " +
842
855
  getProcessUsername() + "; it looks like your system's " +
843
856
  "user database is broken, please fix it.");
@@ -857,17 +870,48 @@ protected:
857
870
  UPDATE_TRACE_POINT();
858
871
  string defaultGroup;
859
872
  string startupFile = absolutizePath(options.getStartupFile(), info.appRoot);
860
- struct passwd *userInfo = NULL;
873
+ struct passwd pwd, *userInfo;
874
+ struct group grp;
861
875
  gid_t groupId = (gid_t) -1;
876
+ long pwdBufSize, grpBufSize;
877
+ shared_array<char> pwdBuf, grpBuf;
878
+ int ret;
862
879
 
880
+ pwdBufSize = sysconf(_SC_GETPW_R_SIZE_MAX);
881
+ if (pwdBufSize == -1) {
882
+ // Let's hope this is enough.
883
+ pwdBufSize = 1024 * 64;
884
+ }
885
+ pwdBuf.reset(new char[pwdBufSize]);
886
+
887
+ grpBufSize = sysconf(_SC_GETGR_R_SIZE_MAX);
888
+ if (grpBufSize == -1) {
889
+ // Let's hope this is enough.
890
+ grpBufSize = 1024 * 64;
891
+ }
892
+ grpBuf.reset(new char[grpBufSize]);
893
+
863
894
  if (options.defaultGroup.empty()) {
864
- struct passwd *info = getpwnam(options.defaultUser.c_str());
865
- if (info == NULL) {
895
+ struct passwd *info;
896
+ struct group *group;
897
+
898
+ info = (struct passwd *) NULL;
899
+ ret = getpwnam_r(options.defaultUser.c_str(), &pwd, pwdBuf.get(),
900
+ pwdBufSize, &info);
901
+ if (ret != 0) {
902
+ info = (struct passwd *) NULL;
903
+ }
904
+ if (info == (struct passwd *) NULL) {
866
905
  throw RuntimeException("Cannot get user database entry for username '" +
867
906
  options.defaultUser + "'");
868
907
  }
869
- struct group *group = getgrgid(info->pw_gid);
870
- if (group == NULL) {
908
+
909
+ group = (struct group *) NULL;
910
+ ret = getgrgid_r(info->pw_gid, &grp, grpBuf.get(), grpBufSize, &group);
911
+ if (ret != 0) {
912
+ group = (struct group *) NULL;
913
+ }
914
+ if (group == (struct group *) NULL) {
871
915
  throw RuntimeException(string("Cannot get group database entry for ") +
872
916
  "the default group belonging to username '" +
873
917
  options.defaultUser + "'");
@@ -878,8 +922,13 @@ protected:
878
922
  }
879
923
 
880
924
  UPDATE_TRACE_POINT();
925
+ userInfo = (struct passwd *) NULL;
881
926
  if (!options.user.empty()) {
882
- userInfo = getpwnam(options.user.c_str());
927
+ ret = getpwnam_r(options.user.c_str(), &pwd, pwdBuf.get(),
928
+ pwdBufSize, &userInfo);
929
+ if (ret != 0) {
930
+ userInfo = (struct passwd *) NULL;
931
+ }
883
932
  } else {
884
933
  struct stat buf;
885
934
  if (syscalls::lstat(startupFile.c_str(), &buf) == -1) {
@@ -887,35 +936,57 @@ protected:
887
936
  throw SystemException("Cannot lstat(\"" + startupFile +
888
937
  "\")", e);
889
938
  }
890
- userInfo = getpwuid(buf.st_uid);
939
+ ret = getpwuid_r(buf.st_uid, &pwd, pwdBuf.get(),
940
+ pwdBufSize, &userInfo);
941
+ if (ret != 0) {
942
+ userInfo = (struct passwd *) NULL;
943
+ }
891
944
  }
892
- if (userInfo == NULL || userInfo->pw_uid == 0) {
893
- userInfo = getpwnam(options.defaultUser.c_str());
945
+ if (userInfo == (struct passwd *) NULL || userInfo->pw_uid == 0) {
946
+ userInfo = (struct passwd *) NULL;
947
+ ret = getpwnam_r(options.defaultUser.c_str(), &pwd,
948
+ pwdBuf.get(), pwdBufSize, &userInfo);
949
+ if (ret != 0) {
950
+ userInfo = (struct passwd *) NULL;
951
+ }
894
952
  }
895
953
 
896
954
  UPDATE_TRACE_POINT();
897
955
  if (!options.group.empty()) {
956
+ struct group *groupInfo = (struct group *) NULL;
957
+
898
958
  if (options.group == "!STARTUP_FILE!") {
899
959
  struct stat buf;
960
+
900
961
  if (syscalls::lstat(startupFile.c_str(), &buf) == -1) {
901
962
  int e = errno;
902
963
  throw SystemException("Cannot lstat(\"" +
903
964
  startupFile + "\")", e);
904
965
  }
905
- if (getgrgid(buf.st_gid) != NULL) {
966
+
967
+ ret = getgrgid_r(buf.st_gid, &grp, grpBuf.get(), grpBufSize,
968
+ &groupInfo);
969
+ if (ret != 0) {
970
+ groupInfo = (struct group *) NULL;
971
+ }
972
+ if (groupInfo != NULL) {
906
973
  groupId = buf.st_gid;
907
974
  } else {
908
975
  groupId = (gid_t) -1;
909
976
  }
910
977
  } else {
911
- struct group *groupInfo = getgrnam(options.group.c_str());
978
+ ret = getgrnam_r(options.group.c_str(), &grp, grpBuf.get(),
979
+ grpBufSize, &groupInfo);
980
+ if (ret != 0) {
981
+ groupInfo = (struct group *) NULL;
982
+ }
912
983
  if (groupInfo != NULL) {
913
984
  groupId = groupInfo->gr_gid;
914
985
  } else {
915
986
  groupId = (gid_t) -1;
916
987
  }
917
988
  }
918
- } else if (userInfo != NULL) {
989
+ } else if (userInfo != (struct passwd *) NULL) {
919
990
  groupId = userInfo->pw_gid;
920
991
  }
921
992
  if (groupId == 0 || groupId == (gid_t) -1) {
@@ -923,7 +994,7 @@ protected:
923
994
  }
924
995
 
925
996
  UPDATE_TRACE_POINT();
926
- if (userInfo == NULL) {
997
+ if (userInfo == (struct passwd *) NULL) {
927
998
  throw RuntimeException("Cannot determine a user to lower privilege to");
928
999
  }
929
1000
  if (groupId == (gid_t) -1) {
@@ -949,7 +1020,7 @@ protected:
949
1020
  #define HAVE_GETGROUPLIST
950
1021
  #endif
951
1022
  #ifdef HAVE_GETGROUPLIST
952
- int ret = getgrouplist(userInfo->pw_name, groupId,
1023
+ ret = getgrouplist(userInfo->pw_name, groupId,
953
1024
  groups, &info.ngroups);
954
1025
  if (ret == -1) {
955
1026
  int e = errno;
@@ -90,7 +90,7 @@
90
90
 
91
91
  #define NGINX_DOC_URL "https://www.phusionpassenger.com/documentation/Users%20guide%20Nginx.html"
92
92
 
93
- #define PASSENGER_VERSION "4.0.46"
93
+ #define PASSENGER_VERSION "4.0.48"
94
94
 
95
95
  #define POOL_HELPER_THREAD_STACK_SIZE 262144
96
96
 
@@ -25,6 +25,7 @@
25
25
 
26
26
  #include <oxt/system_calls.hpp>
27
27
  #include <boost/thread.hpp>
28
+ #include <boost/shared_array.hpp>
28
29
 
29
30
  #include <cassert>
30
31
  #include <cstdlib>
@@ -38,6 +39,8 @@
38
39
  #include <fcntl.h>
39
40
  #include <poll.h>
40
41
  #include <dirent.h>
42
+ #include <pwd.h>
43
+ #include <grp.h>
41
44
  #include <limits.h>
42
45
  #include <unistd.h>
43
46
  #include <string.h>
@@ -381,21 +384,25 @@ escapeForXml(const StaticString &input) {
381
384
  string
382
385
  getProcessUsername() {
383
386
  struct passwd pwd, *result;
384
- char strings[1024];
385
- int ret;
386
-
387
+ long bufSize;
388
+ shared_array<char> strings;
389
+
390
+ bufSize = sysconf(_SC_GETPW_R_SIZE_MAX);
391
+ if (bufSize == -1) {
392
+ // Let's hope this is enough.
393
+ bufSize = 1024 * 64;
394
+ }
395
+ strings.reset(new char[bufSize]);
396
+
387
397
  result = (struct passwd *) NULL;
388
- do {
389
- ret = getpwuid_r(getuid(), &pwd, strings, sizeof(strings), &result);
390
- } while (ret == -1 && errno == EINTR);
391
- if (ret == -1) {
398
+ if (getpwuid_r(getuid(), &pwd, strings.get(), bufSize, &result) != 0) {
392
399
  result = (struct passwd *) NULL;
393
400
  }
394
-
401
+
395
402
  if (result == (struct passwd *) NULL || result->pw_name == NULL || result->pw_name[0] == '\0') {
396
- snprintf(strings, sizeof(strings), "UID %lld", (long long) getuid());
397
- strings[sizeof(strings) - 1] = '\0';
398
- return strings;
403
+ snprintf(strings.get(), bufSize, "UID %lld", (long long) getuid());
404
+ strings.get()[bufSize - 1] = '\0';
405
+ return strings.get();
399
406
  } else {
400
407
  return result->pw_name;
401
408
  }
@@ -403,10 +410,23 @@ getProcessUsername() {
403
410
 
404
411
  string
405
412
  getGroupName(gid_t gid) {
406
- struct group *groupEntry;
413
+ struct group grp, *groupEntry;
414
+ long bufSize;
415
+ shared_array<char> strings;
416
+
417
+ bufSize = sysconf(_SC_GETGR_R_SIZE_MAX);
418
+ if (bufSize == -1) {
419
+ // Let's hope this is enough.
420
+ bufSize = 1024 * 64;
421
+ }
422
+ strings.reset(new char[bufSize]);
423
+
424
+ groupEntry = (struct group *) NULL;
425
+ if (getgrgid_r(gid, &grp, strings.get(), bufSize, &groupEntry) != 0) {
426
+ groupEntry = (struct group *) NULL;
427
+ }
407
428
 
408
- groupEntry = getgrgid(gid);
409
- if (groupEntry == NULL) {
429
+ if (groupEntry == (struct group *) NULL) {
410
430
  return toString(gid);
411
431
  } else {
412
432
  return groupEntry->gr_name;
@@ -415,10 +435,23 @@ getGroupName(gid_t gid) {
415
435
 
416
436
  gid_t
417
437
  lookupGid(const string &groupName) {
418
- struct group *groupEntry;
438
+ struct group grp, *groupEntry;
439
+ long bufSize;
440
+ shared_array<char> strings;
441
+
442
+ bufSize = sysconf(_SC_GETGR_R_SIZE_MAX);
443
+ if (bufSize == -1) {
444
+ // Let's hope this is enough.
445
+ bufSize = 1024 * 64;
446
+ }
447
+ strings.reset(new char[bufSize]);
448
+
449
+ groupEntry = (struct group *) NULL;
450
+ if (getgrnam_r(groupName.c_str(), &grp, strings.get(), bufSize, &groupEntry) != 0) {
451
+ groupEntry = (struct group *) NULL;
452
+ }
419
453
 
420
- groupEntry = getgrnam(groupName.c_str());
421
- if (groupEntry == NULL) {
454
+ if (groupEntry == (struct group *) NULL) {
422
455
  if (looksLikePositiveNumber(groupName)) {
423
456
  return atoi(groupName);
424
457
  } else {
@@ -829,7 +829,7 @@ private:
829
829
  }
830
830
 
831
831
  short fracToShort(double x) const {
832
- return x * SHRT_MAX;
832
+ return (short) (x * SHRT_MAX);
833
833
  }
834
834
 
835
835
  void updateCpuMetrics(SystemMetrics::CpuUsage &cpuUsage, long long user, long long nice,
@@ -41,7 +41,7 @@ struct Options {
41
41
  SystemMetrics::XmlOptions xmlOptions;
42
42
  SystemMetrics::DescriptionOptions descOptions;
43
43
  int interval;
44
- bool stdin;
44
+ bool useStdin;
45
45
  bool exitOnUnexpectedError;
46
46
  bool help;
47
47
 
@@ -49,7 +49,7 @@ struct Options {
49
49
  xml = false;
50
50
  descOptions.colors = isatty(1);
51
51
  interval = -1;
52
- stdin = false;
52
+ useStdin = false;
53
53
  exitOnUnexpectedError = true;
54
54
  help = false;
55
55
  }
@@ -117,7 +117,7 @@ parseOptions(int argc, char *argv[]) {
117
117
  exit(1);
118
118
  }
119
119
  } else if (isFlag(argv[i], '\0', "--stdin")) {
120
- options.stdin = true;
120
+ options.useStdin = true;
121
121
  i++;
122
122
  } else if (isFlag(argv[i], '\0', "--no-exit-on-unexpected-error")) {
123
123
  options.exitOnUnexpectedError = false;
@@ -131,7 +131,7 @@ parseOptions(int argc, char *argv[]) {
131
131
  exit(1);
132
132
  }
133
133
  }
134
- if (options.interval != -1 && options.stdin) {
134
+ if (options.interval != -1 && options.useStdin) {
135
135
  fprintf(stderr, "ERROR: --watch and --stdin are mutually exclusive.\n");
136
136
  exit(1);
137
137
  }
@@ -181,7 +181,7 @@ main(int argc, char *argv[]) {
181
181
  usleep(50000);
182
182
  }
183
183
 
184
- if (options.stdin) {
184
+ if (options.useStdin) {
185
185
  while (waitForNextLine()) {
186
186
  perform(options, collector, metrics);
187
187
  }
@@ -30,7 +30,7 @@ module PhusionPassenger
30
30
 
31
31
  PACKAGE_NAME = 'passenger'
32
32
  # Run 'rake ext/common/Constants.h' after changing this number.
33
- VERSION_STRING = '4.0.46'
33
+ VERSION_STRING = '4.0.48'
34
34
 
35
35
  PREFERRED_NGINX_VERSION = '1.6.0'
36
36
  NGINX_SHA256_CHECKSUM = '943ad757a1c3e8b3df2d5c4ddacc508861922e36fa10ea6f8e3a348fc9abfc1a'
@@ -122,12 +122,12 @@ private
122
122
  paths.concat(output.split(':'))
123
123
  end
124
124
 
125
- paths.delete(gem_bindir)
126
- paths.delete(homebrew_bindir)
127
- paths.delete(PhusionPassenger.bin_dir)
128
125
  # These may not be in PATH if the user did not run this command through sudo.
129
126
  paths << "/usr/bin"
130
127
  paths << "/usr/sbin"
128
+ paths.delete(gem_bindir)
129
+ paths.delete(homebrew_bindir)
130
+ paths.delete(PhusionPassenger.bin_dir)
131
131
  paths.uniq!
132
132
 
133
133
  other_installs = []
@@ -25,7 +25,7 @@
25
25
  PhusionPassenger.require_passenger_lib 'constants'
26
26
  PhusionPassenger.require_passenger_lib 'public_api'
27
27
  PhusionPassenger.require_passenger_lib 'debug_logging'
28
- require 'shellwords'
28
+ PhusionPassenger.require_passenger_lib 'utils/shellwords'
29
29
 
30
30
  module PhusionPassenger
31
31
 
@@ -138,11 +138,11 @@ private
138
138
  STDERR.puts " --> Downloading precompiled #{library_name} for the current Ruby interpreter..."
139
139
  STDERR.puts " (set PASSENGER_DOWNLOAD_NATIVE_SUPPORT_BINARY=0 to disable)"
140
140
 
141
- require 'shellwords'
142
141
  require 'logger'
143
142
  PhusionPassenger.require_passenger_lib 'platform_info/ruby'
144
143
  PhusionPassenger.require_passenger_lib 'utils/tmpio'
145
144
  PhusionPassenger.require_passenger_lib 'utils/download'
145
+ PhusionPassenger.require_passenger_lib 'utils/shellwords'
146
146
 
147
147
  PhusionPassenger::Utils.mktmpdir("passenger-native-support-") do |dir|
148
148
  Dir.chdir(dir) do
@@ -215,7 +215,7 @@ private
215
215
  STDERR.puts " (set PASSENGER_COMPILE_NATIVE_SUPPORT_BINARY=0 to disable)"
216
216
 
217
217
  require 'fileutils'
218
- require 'shellwords'
218
+ PhusionPassenger.require_passenger_lib 'utils/shellwords'
219
219
  PhusionPassenger.require_passenger_lib 'platform_info/ruby'
220
220
 
221
221
  target_dir = compile(installation_target_dirs)
@@ -23,8 +23,8 @@
23
23
  # THE SOFTWARE.
24
24
 
25
25
  PhusionPassenger.require_passenger_lib 'platform_info'
26
+ PhusionPassenger.require_passenger_lib 'utils/shellwords'
26
27
  require 'fileutils'
27
- require 'shellwords'
28
28
 
29
29
  module PhusionPassenger
30
30
  module Utils
@@ -0,0 +1,29 @@
1
+ # Polyfill for the shellwords library on Ruby 1.8.5.
2
+
3
+ require 'shellwords'
4
+
5
+ if !Shellwords.respond_to?(:escape)
6
+ Shellwords.class_eval do
7
+ def self.escape(str)
8
+ # An empty argument will be skipped, so return empty quotes.
9
+ return "''" if str.empty?
10
+ str = str.dup
11
+ # Treat multibyte characters as is. It is caller's responsibility
12
+ # to encode the string in the right encoding for the shell
13
+ # environment.
14
+ str.gsub!(/([^A-Za-z0-9_\-.,:\/@\n])/, "\\\\\\1")
15
+ # A LF cannot be escaped with a backslash because a backslash + LF
16
+ # combo is regarded as line continuation and simply ignored.
17
+ str.gsub!(/\n/, "'\n'")
18
+ return str
19
+ end
20
+ end
21
+ end
22
+
23
+ if !Shellwords.respond_to?(:join)
24
+ Shellwords.class_eval do
25
+ def self.join(array)
26
+ array.map { |arg| escape(arg) }.join(' ')
27
+ end
28
+ end
29
+ end
@@ -151,7 +151,7 @@ http {
151
151
  <% end %>
152
152
 
153
153
  # Rails asset pipeline support.
154
- location ~ ^/assets/ {
154
+ location ~ "^/assets/.+-[0-9a-f]{32}\..+" {
155
155
  error_page 490 = @static_asset;
156
156
  error_page 491 = @dynamic_request;
157
157
  recursive_error_pages on;
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: passenger
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.46
4
+ version: 4.0.48
5
5
  platform: ruby
6
6
  authors:
7
7
  - Phusion - http://www.phusion.nl/
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-07-14 00:00:00.000000000 Z
11
+ date: 2014-07-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -123,13 +123,12 @@ files:
123
123
  - debian.template/patches/series
124
124
  - debian.template/rules.template
125
125
  - debian.template/source/format
126
- - dev/copy_boost_headers.rb
127
- - dev/find_owner_pipe_leaks.rb
126
+ - dev/copy_boost_headers
128
127
  - dev/install_scripts_bootstrap_code.rb
129
- - dev/list_tests.rb
128
+ - dev/list_tests
130
129
  - dev/rack.test/config.ru
131
130
  - dev/rack.test/public/asset.txt
132
- - dev/render_error_pages.rb
131
+ - dev/rpmtool
133
132
  - dev/run_travis.sh
134
133
  - dev/runner
135
134
  - dev/test_rpm_packaging.sh
@@ -2456,6 +2455,7 @@ files:
2456
2455
  - lib/phusion_passenger/utils/json.rb
2457
2456
  - lib/phusion_passenger/utils/lock.rb
2458
2457
  - lib/phusion_passenger/utils/native_support_utils.rb
2458
+ - lib/phusion_passenger/utils/shellwords.rb
2459
2459
  - lib/phusion_passenger/utils/tee_input.rb
2460
2460
  - lib/phusion_passenger/utils/terminal_choice_menu.rb
2461
2461
  - lib/phusion_passenger/utils/tmpdir.rb
metadata.gz.asc CHANGED
@@ -2,11 +2,11 @@
2
2
  Version: GnuPG/MacGPG2 v2.0.17 (Darwin)
3
3
  Comment: GPGTools - http://gpgtools.org
4
4
 
5
- iQEcBAABAgAGBQJTxCOxAAoJECrHRaUKISqMXVwIAI0rKA8XrET+UEEZxdg0KApM
6
- 9To5MBumjeAEjNifX89upFHpSw+pXbOGz0xggl8h1y0axsDL8fQuXS7nWKWy4o6u
7
- FbOBo3BBH9Ji0e6G/LlPe2NbYGxHLGUEmFER1/qXwO4PffdR3+gRnjEJEucs4aPJ
8
- 1qbrne5R3svh2vRFnzJMRHdP8cBYXz1DS/DK4xY0aQ10RK6Ah7C2zrhTBudezqUp
9
- dXnnDa8Pcc/i0j1v2bZISOYp7nwhs+akf+c9/z3dZBpoIDPN2USt5IMyb5B4/ueT
10
- SFgRk/kStS95XwIlAb6a+PzDGjEfL/qVxVjQDb2GjgihP7vQEzWMzeTumbZa16g=
11
- =k1B4
5
+ iQEcBAABAgAGBQJT0PH2AAoJECrHRaUKISqM3rUH/AsN9NOP4ynTb+acSScLq/I/
6
+ nF1Qv9XA8CW23M6Mx9boMgGcVC0B6NOP5I6T8WMHDBL3J6XLCOox0FeQ0kwAS1pZ
7
+ y4uHVwNPvl3JTS8h2c50y7JeixN/WQodXvgb9WvtV6vJQKKaqQ65wAFKo2yk4Nn8
8
+ hRipGYgrpuZsRG8/qKvk5iBa6qkWLrHWhWbekY/hS/zMAh+UlwV5UwUlL+Q8cf5L
9
+ dOpPxu9qj1Fw2gdIRON4VJ/nW+MiH0skGCdtaLdVs+/aFW2DcF/5G28lcV7X1ANb
10
+ vXL5NWRRM/ZveskFCFdbm5Irhp/dnf5PqPvoyljqsJh2O34e3PizXXtTN9a9kEw=
11
+ =UGA6
12
12
  -----END PGP SIGNATURE-----
@@ -1,128 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # Phusion Passenger - https://www.phusionpassenger.com/
3
- # Copyright (c) 2010 Phusion
4
- #
5
- # "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
6
- #
7
- # Permission is hereby granted, free of charge, to any person obtaining a copy
8
- # of this software and associated documentation files (the "Software"), to deal
9
- # in the Software without restriction, including without limitation the rights
10
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
- # copies of the Software, and to permit persons to whom the Software is
12
- # furnished to do so, subject to the following conditions:
13
- #
14
- # The above copyright notice and this permission notice shall be included in
15
- # all copies or substantial portions of the Software.
16
- #
17
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
- # THE SOFTWARE.
24
- ##############################################################################
25
- # A script for finding owner pipe leaks in Apache. An owner pipe is considered
26
- # to be leaked if it is owned by two or more Apache processes.
27
- #
28
- # This script only works on Linux. Only run it when Apache is idle.
29
-
30
- $LOAD_PATH << "#{File.dirname(__FILE__)}/../lib"
31
- require 'set'
32
- require 'passenger/platform_info'
33
-
34
- include PlatformInfo
35
-
36
- def list_pids
37
- Dir.chdir("/proc") do
38
- return Dir["*"].select do |x|
39
- x =~ /^\d+$/
40
- end
41
- end
42
- end
43
-
44
- def list_pipes(pid)
45
- pipes = []
46
- Dir["/proc/#{pid}/fd/*"].each do |file|
47
- if File.symlink?(file) && File.readlink(file) =~ /^pipe:\[(.*)\]$/
48
- pipes << $1
49
- end
50
- end
51
- return pipes
52
- end
53
-
54
- def is_rails_app(pid)
55
- return File.read("/proc/#{pid}/cmdline") =~ /^Rails: /
56
- end
57
-
58
- def is_apache(pid)
59
- begin
60
- return File.readlink("/proc/#{pid}/exe") == HTTPD
61
- rescue
62
- return false
63
- end
64
- end
65
-
66
- # Returns a pair of these items:
67
- # - The owner pipe map. Maps a Rails application's PID to to its owner pipe's ID.
68
- # - The reverse map. Maps an owner pipe ID to the Rail application's PID.
69
- def create_owner_pipe_map
70
- map = {}
71
- reverse_map = {}
72
- list_pids.select{ |x| is_rails_app(x) }.each do |pid|
73
- owner_pipe = list_pipes(pid).first
74
- map[pid] = owner_pipe
75
- reverse_map[owner_pipe] = pid
76
- end
77
- return [map, reverse_map]
78
- end
79
-
80
- def show_owner_pipe_listing(map, reverse_map)
81
- puts "------------ Owner pipe listing ------------"
82
- count = 0
83
- list_pids.select{ |x| is_apache(x) }.sort.each do |pid|
84
- list_pipes(pid).select do |pipe|
85
- reverse_map.has_key?(pipe)
86
- end.each do |pipe|
87
- puts "Apache PID #{pid} holds the owner pipe (#{pipe}) " <<
88
- "for Rails PID #{reverse_map[pipe]}"
89
- count += 1
90
- end
91
- end
92
- if count == 0
93
- puts "(none)"
94
- end
95
- puts ""
96
- end
97
-
98
- def show_owner_pipe_leaks(map, reverse_map)
99
- apache_owner_pipe_map = {}
100
- list_pids.select{ |x| is_apache(x) }.sort.each do |pid|
101
- list_pipes(pid).select do |pipe|
102
- reverse_map.has_key?(pipe)
103
- end.each do |pipe|
104
- apache_owner_pipe_map[pipe] ||= []
105
- apache_owner_pipe_map[pipe] << pid
106
- end
107
- end
108
-
109
- puts "------------ Leaks ------------"
110
- count = 0
111
- apache_owner_pipe_map.each_pair do |pipe, pids|
112
- if pids.size >= 2
113
- puts "Rails PID #{reverse_map[pipe]} owned by Apache processes: #{pids.join(", ")}"
114
- count += 1
115
- end
116
- end
117
- if count == 0
118
- puts "(none)"
119
- end
120
- end
121
-
122
- def start
123
- map, reverse_map = create_owner_pipe_map
124
- show_owner_pipe_listing(map, reverse_map)
125
- show_owner_pipe_leaks(map, reverse_map)
126
- end
127
-
128
- start
@@ -1,116 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # Phusion Passenger - https://www.phusionpassenger.com/
3
- # Copyright (c) 2010 Phusion
4
- #
5
- # "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
6
- #
7
- # Permission is hereby granted, free of charge, to any person obtaining a copy
8
- # of this software and associated documentation files (the "Software"), to deal
9
- # in the Software without restriction, including without limitation the rights
10
- # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
- # copies of the Software, and to permit persons to whom the Software is
12
- # furnished to do so, subject to the following conditions:
13
- #
14
- # The above copyright notice and this permission notice shall be included in
15
- # all copies or substantial portions of the Software.
16
- #
17
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
- # THE SOFTWARE.
24
-
25
- $LOAD_PATH.unshift("#{File.dirname(__FILE__)}/../lib")
26
- $LOAD_PATH.unshift("#{File.dirname(__FILE__)}/../ext")
27
- require 'phusion_passenger/html_template'
28
- require 'phusion_passenger/spawn_manager'
29
- require 'phusion_passenger/platform_info'
30
- include PhusionPassenger
31
-
32
- if !defined?(Mysql::Error)
33
- module Mysql
34
- class Error < StandardError
35
- end
36
- end
37
- end
38
-
39
- def create_dummy_exception
40
- begin
41
- raise StandardError, "A dummy exception."
42
- rescue => e
43
- return e
44
- end
45
- end
46
-
47
- def create_database_exception
48
- begin
49
- raise Mysql::Error, "Cannot connect to database localhost:12345: connection refused (1234)"
50
- rescue => e
51
- return e
52
- end
53
- end
54
-
55
- def create_dummy_backtrace
56
- dummy_backtrace = nil
57
- begin
58
- raise StandardError, "A dummy exception."
59
- rescue => e
60
- dummy_backtrace = e.backtrace
61
- end
62
- dummy_backtrace.unshift("/webapps/foo/app/models/Foo.rb:102:in `something`")
63
- dummy_backtrace.unshift("/webapps/foo/config/environment.rb:10")
64
- return dummy_backtrace
65
- end
66
-
67
- def render_error_page(exception, output, template)
68
- exception.set_backtrace(create_dummy_backtrace)
69
- File.open(output, 'w') do |f|
70
- template = HTMLTemplate.new(template,
71
- :error => exception, :app_root => "/foo/bar")
72
- f.write(template.result)
73
- puts "Written '#{output}'"
74
- end
75
- end
76
-
77
- def start
78
- bt = create_dummy_backtrace
79
-
80
- e = FrameworkInitError.new("Some error message",
81
- create_dummy_exception,
82
- :vendor => '/webapps/foo')
83
- render_error_page(e, 'framework_init_error_with_vendor.html',
84
- 'framework_init_error')
85
-
86
- e = FrameworkInitError.new("Some error message",
87
- create_dummy_exception,
88
- :version => '1.2.3')
89
- render_error_page(e, 'framework_init_error.html',
90
- 'framework_init_error')
91
-
92
- e = VersionNotFound.new("Some error message", '>= 1.0.2')
93
- render_error_page(e, 'version_not_found.html',
94
- 'version_not_found')
95
-
96
- e = AppInitError.new("Some error message", create_dummy_exception)
97
- render_error_page(e, 'app_init_error.html',
98
- 'app_init_error')
99
-
100
- e = AppInitError.new("Some error message", create_database_exception)
101
- render_error_page(e, 'database_error.html',
102
- 'database_error')
103
-
104
- e = ArgumentError.new("Some error message")
105
- render_error_page(e, 'invalid_app_root.html',
106
- 'invalid_app_root')
107
-
108
- e = StandardError.new("Some error message")
109
- render_error_page(e, 'general_error.html',
110
- 'general_error')
111
-
112
- e = AppInitError.new("Some error message", create_dummy_exception)
113
- render_error_page(e, 'app_exited.html', 'app_exited_during_initialization')
114
- end
115
-
116
- start