passenger 5.0.5 → 5.0.6

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 (36) hide show
  1. checksums.yaml +8 -8
  2. checksums.yaml.gz.asc +7 -7
  3. data.tar.gz.asc +7 -7
  4. data/CHANGELOG +17 -0
  5. data/build/test_basics.rb +2 -2
  6. data/doc/Users guide Apache.html +47 -42
  7. data/doc/Users guide Apache.idmap.txt +23 -21
  8. data/doc/Users guide Nginx.html +47 -42
  9. data/doc/Users guide Nginx.idmap.txt +23 -21
  10. data/doc/Users guide Standalone.html +39 -34
  11. data/doc/Users guide Standalone.idmap.txt +19 -17
  12. data/doc/users_guide_snippets/installation.txt +5 -0
  13. data/ext/apache2/Configuration.hpp +0 -12
  14. data/ext/apache2/Hooks.cpp +31 -35
  15. data/ext/common/AgentsStarter.h +24 -19
  16. data/ext/common/BackgroundEventLoop.cpp +1 -0
  17. data/ext/common/Constants.h +1 -1
  18. data/ext/common/MemoryKit/mbuf.cpp +4 -0
  19. data/ext/common/ResourceLocator.h +1 -1
  20. data/ext/common/ServerKit/Context.h +20 -0
  21. data/ext/common/ServerKit/HeaderTable.h +12 -4
  22. data/ext/common/ServerKit/HttpHeaderParser.h +2 -2
  23. data/ext/common/agents/HelperAgent/RequestHandler.h +2 -0
  24. data/ext/common/agents/HelperAgent/RequestHandler/BufferBody.cpp +4 -2
  25. data/ext/common/agents/HelperAgent/RequestHandler/Client.h +3 -1
  26. data/ext/common/agents/HelperAgent/RequestHandler/ForwardResponse.cpp +7 -0
  27. data/ext/common/agents/HelperAgent/RequestHandler/Hooks.cpp +5 -0
  28. data/ext/common/agents/HelperAgent/RequestHandler/SendRequest.cpp +34 -1
  29. data/ext/common/agents/HelperAgent/ResponseCache.h +14 -2
  30. data/ext/common/agents/Watchdog/HelperAgentWatcher.cpp +2 -2
  31. data/lib/phusion_passenger.rb +1 -1
  32. data/lib/phusion_passenger/config/admin_command_command.rb +52 -12
  33. data/lib/phusion_passenger/config/utils.rb +1 -1
  34. data/lib/phusion_passenger/standalone/start_command.rb +8 -3
  35. metadata +2 -2
  36. metadata.gz.asc +7 -7
@@ -162,6 +162,7 @@ BackgroundEventLoop::stop() {
162
162
  if (priv->thr != NULL) {
163
163
  ev_async_send(loop, async);
164
164
  priv->thr->join();
165
+ delete priv->thr;
165
166
  priv->thr = NULL;
166
167
  }
167
168
  }
@@ -114,7 +114,7 @@
114
114
 
115
115
  #define NGINX_DOC_URL "https://www.phusionpassenger.com/documentation/Users%20guide%20Nginx.html"
116
116
 
117
- #define PASSENGER_VERSION "5.0.5"
117
+ #define PASSENGER_VERSION "5.0.6"
118
118
 
119
119
  #define POOL_HELPER_THREAD_STACK_SIZE 262144
120
120
 
@@ -151,6 +151,10 @@ mbuf_block_put(struct mbuf_block *mbuf_block)
151
151
  mbuf_block->pool->nfree_mbuf_blockq++;
152
152
  mbuf_block->pool->nactive_mbuf_blockq--;
153
153
  STAILQ_INSERT_HEAD(&mbuf_block->pool->free_mbuf_blockq, mbuf_block, next);
154
+
155
+ #ifdef MBUF_ENABLE_DEBUGGING
156
+ TAILQ_REMOVE(&mbuf_block->pool->active_mbuf_blockq, mbuf_block, active_q);
157
+ #endif
154
158
  }
155
159
 
156
160
  /*
@@ -169,7 +169,7 @@ public:
169
169
  return path;
170
170
  }
171
171
 
172
- throw RuntimeException("Support binary " + name + " not found");
172
+ throw RuntimeException("Support binary " + name + " not found (tried: " + getSupportBinariesDir() + "/" + name + " and " + path + ")");
173
173
  }
174
174
  };
175
175
 
@@ -98,6 +98,26 @@ public:
98
98
  * mbuf_pool.mbuf_block_chunk_size);
99
99
  mbufDoc["active_memory"] = byteSizeToJson(mbuf_pool.nactive_mbuf_blockq
100
100
  * mbuf_pool.mbuf_block_chunk_size);
101
+ #ifdef MBUF_ENABLE_DEBUGGING
102
+ struct MemoryKit::active_mbuf_block_list *list =
103
+ const_cast<struct MemoryKit::active_mbuf_block_list *>(
104
+ &mbuf_pool.active_mbuf_blockq);
105
+ struct MemoryKit::mbuf_block *block;
106
+ Json::Value listJson(Json::arrayValue);
107
+
108
+ TAILQ_FOREACH (block, list, active_q) {
109
+ Json::Value blockJson;
110
+ blockJson["refcount"] = block->refcount;
111
+ #ifdef MBUF_ENABLE_BACKTRACES
112
+ blockJson["backtrace"] =
113
+ (block->backtrace == NULL)
114
+ ? "(null)"
115
+ : block->backtrace;
116
+ #endif
117
+ listJson.append(blockJson);
118
+ }
119
+ mbufDoc["active_blocks_list"] = listJson;
120
+ #endif
101
121
 
102
122
  doc["mbuf_pool"] = mbufDoc;
103
123
 
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * Phusion Passenger - https://www.phusionpassenger.com/
3
- * Copyright (c) 2014 Phusion
3
+ * Copyright (c) 2014-2015 Phusion
4
4
  *
5
5
  * "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
6
6
  *
@@ -239,8 +239,13 @@ public:
239
239
  return const_cast<LString *>(static_cast<const HeaderTable *>(this)->lookup(key));
240
240
  }
241
241
 
242
- /** header must stay alive */
243
- void insert(Header *header, psg_pool_t *pool) {
242
+ /**
243
+ * HeaderTable takes over ownership of `header`. But you must ensure that the pool
244
+ * that the header was allocated from is not destroyed before the HeaderTable
245
+ * is destroyed or cleared.
246
+ */
247
+ void insert(Header **headerPtr, psg_pool_t *pool) {
248
+ Header *header = *headerPtr;
244
249
  assert(header->key.size < MAX_KEY_LENGTH);
245
250
 
246
251
  if (m_cells == NULL) {
@@ -260,6 +265,7 @@ public:
260
265
  m_population++;
261
266
 
262
267
  cell->header = header;
268
+ *headerPtr = NULL;
263
269
  return;
264
270
  } else if (psg_lstr_cmp(&cell->header->key, &header->key)) {
265
271
  // Cell matches, so merge value into header.
@@ -278,6 +284,8 @@ public:
278
284
  psg_lstr_append_part(&cell->header->val, part);
279
285
  part = next;
280
286
  }
287
+ psg_lstr_deinit(&header->key);
288
+ *headerPtr = NULL;
281
289
  return;
282
290
  } else {
283
291
  cell = PHT_CIRCULAR_NEXT(cell);
@@ -295,7 +303,7 @@ public:
295
303
  psg_lstr_init(&header->val);
296
304
  psg_lstr_append(&header->val, pool, value.data(), value.size());
297
305
  header->hash = name.hash();
298
- insert(header, pool);
306
+ insert(&header, pool);
299
307
  return header;
300
308
  }
301
309
 
@@ -106,9 +106,9 @@ private:
106
106
 
107
107
  void insertCurrentHeader() {
108
108
  if (!state->secureMode) {
109
- message->headers.insert(state->currentHeader, pool);
109
+ message->headers.insert(&state->currentHeader, pool);
110
110
  } else {
111
- message->secureHeaders.insert(state->currentHeader, pool);
111
+ message->secureHeaders.insert(&state->currentHeader, pool);
112
112
  }
113
113
  }
114
114
 
@@ -45,6 +45,8 @@
45
45
  #include <utility>
46
46
  #include <typeinfo>
47
47
  #include <cstdio>
48
+ #include <cstdlib>
49
+ #include <cstddef>
48
50
  #include <cassert>
49
51
  #include <cctype>
50
52
 
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * Phusion Passenger - https://www.phusionpassenger.com/
3
- * Copyright (c) 2011-2014 Phusion
3
+ * Copyright (c) 2011-2015 Phusion
4
4
  *
5
5
  * "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
6
6
  *
@@ -34,6 +34,7 @@ beginBufferingBody(Client *client, Request *req) {
34
34
  req->bodyChannel.start();
35
35
  req->bodyBuffer.reinitialize();
36
36
  req->bodyBuffer.stop();
37
+ req->beginScopeLog(&req->scopeLogs.bufferingRequestBody, "buffering request body");
37
38
  }
38
39
 
39
40
  Channel::Result
@@ -77,8 +78,9 @@ whenBufferingBody_onRequestBody(Client *client, Request *req,
77
78
  sizeof("content-length") - 1).hash();
78
79
 
79
80
  req->headers.erase(HTTP_TRANSFER_ENCODING);
80
- req->headers.insert(header, req->pool);
81
+ req->headers.insert(&header, req->pool);
81
82
  }
83
+ req->endScopeLog(&req->scopeLogs.bufferingRequestBody);
82
84
  checkoutSession(client, req);
83
85
  return Channel::Result(0, true);
84
86
  } else {
@@ -43,7 +43,9 @@ public:
43
43
 
44
44
  Client(void *server)
45
45
  : ServerKit::BaseHttpClient<Request>(server)
46
- { }
46
+ {
47
+ SERVER_KIT_BASE_HTTP_CLIENT_INIT();
48
+ }
47
49
 
48
50
  DEFINE_SERVER_KIT_BASE_HTTP_CLIENT_FOOTER(Client, Request);
49
51
  };
@@ -981,6 +981,7 @@ void
981
981
  handleAppResponseBodyEnd(Client *client, Request *req) {
982
982
  keepAliveAppConnection(client, req);
983
983
  storeAppResponseInTurboCache(client, req);
984
+ finalizeUnionStationWithSuccess(client, req);
984
985
  }
985
986
 
986
987
  OXT_FORCE_INLINE void
@@ -1022,3 +1023,9 @@ storeAppResponseInTurboCache(Client *client, Request *req) {
1022
1023
  }
1023
1024
  }
1024
1025
  }
1026
+
1027
+ void
1028
+ finalizeUnionStationWithSuccess(Client *client, Request *req) {
1029
+ req->endScopeLog(&req->scopeLogs.requestProcessing, true);
1030
+ req->endScopeLog(&req->scopeLogs.requestProxying, true);
1031
+ }
@@ -114,6 +114,8 @@ virtual void deinitializeRequest(Client *client, Request *req) {
114
114
  req->endScopeLog(&req->scopeLogs.bufferingRequestBody, false);
115
115
  req->endScopeLog(&req->scopeLogs.requestProcessing, false);
116
116
 
117
+ req->options.transaction.reset();
118
+
117
119
  req->appSink.setConsumedCallback(NULL);
118
120
  req->appSink.deinitialize();
119
121
  req->appSource.deinitialize();
@@ -185,6 +187,9 @@ void deinitializeAppResponse(Client *client, Request *req) {
185
187
  resp->headers.clear();
186
188
  resp->secureHeaders.clear();
187
189
 
190
+ if (resp->setCookie != NULL) {
191
+ psg_lstr_deinit(resp->setCookie);
192
+ }
188
193
  psg_lstr_deinit(&resp->bodyCacheBuffer);
189
194
  }
190
195
 
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * Phusion Passenger - https://www.phusionpassenger.com/
3
- * Copyright (c) 2011-2014 Phusion
3
+ * Copyright (c) 2011-2015 Phusion
4
4
  *
5
5
  * "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
6
6
  *
@@ -89,7 +89,17 @@ struct SessionProtocolWorkingState {
89
89
  const LString *remoteUser;
90
90
  const LString *contentType;
91
91
  const LString *contentLength;
92
+ char *environmentVariablesData;
93
+ size_t environmentVariablesSize;
92
94
  bool hasBaseURI;
95
+
96
+ SessionProtocolWorkingState()
97
+ : environmentVariablesData(NULL)
98
+ { }
99
+
100
+ ~SessionProtocolWorkingState() {
101
+ free(environmentVariablesData);
102
+ }
93
103
  };
94
104
 
95
105
  void
@@ -183,6 +193,21 @@ determineHeaderSizeForSessionProtocol(Request *req,
183
193
  } else {
184
194
  state.contentLength = NULL;
185
195
  }
196
+ if (!req->options.environmentVariables.empty()) {
197
+ size_t len = modp_b64_decode_len(req->options.environmentVariables.size());
198
+ state.environmentVariablesData = (char *) malloc(len);
199
+ if (state.environmentVariablesData == NULL) {
200
+ throw RuntimeException("Unable to allocate memory for base64 "
201
+ "decoding of environment variables");
202
+ }
203
+ len = modp_b64_decode(state.environmentVariablesData,
204
+ req->options.environmentVariables.data(),
205
+ req->options.environmentVariables.size());
206
+ if (len == (size_t) -1) {
207
+ throw RuntimeException("Unable to base64 decode environment variables");
208
+ }
209
+ state.environmentVariablesSize = len;
210
+ }
186
211
 
187
212
  dataSize += sizeof("REQUEST_URI");
188
213
  dataSize += req->path.size + 1;
@@ -289,6 +314,10 @@ determineHeaderSizeForSessionProtocol(Request *req,
289
314
  it.next();
290
315
  }
291
316
 
317
+ if (state.environmentVariablesData != NULL) {
318
+ dataSize += state.environmentVariablesSize;
319
+ }
320
+
292
321
  return dataSize + 1;
293
322
  }
294
323
 
@@ -427,6 +456,10 @@ constructHeaderForSessionProtocol(Request *req, char * restrict buffer, unsigned
427
456
  it.next();
428
457
  }
429
458
 
459
+ if (state.environmentVariablesData != NULL) {
460
+ pos = appendData(pos, end, state.environmentVariablesData, state.environmentVariablesSize);
461
+ }
462
+
430
463
  Uint32Message::generate(buffer, pos - buffer - sizeof(boost::uint32_t));
431
464
 
432
465
  size = pos - buffer;
@@ -60,7 +60,10 @@ public:
60
60
  time_t date;
61
61
 
62
62
  Header()
63
- : valid(false)
63
+ : valid(false),
64
+ keySize(0),
65
+ hash(0),
66
+ date(0)
64
67
  { }
65
68
  };
66
69
 
@@ -72,6 +75,14 @@ public:
72
75
  char httpHeaderData[MAX_HEADER_SIZE];
73
76
  // This data is dechunked.
74
77
  char httpBodyData[MAX_BODY_SIZE];
78
+
79
+ Body()
80
+ : httpHeaderSize(0),
81
+ httpBodySize(0),
82
+ expiryDate(0)
83
+ {
84
+ key[0] = httpHeaderData[0] = httpBodyData[0] = '\0';
85
+ }
75
86
  };
76
87
 
77
88
  struct Entry {
@@ -571,7 +582,8 @@ public:
571
582
  req->appResponse.cacheControl->start->data,
572
583
  req->appResponse.cacheControl->size);
573
584
  if (cacheControl.find(P_STATIC_STRING("no-store")) != string::npos
574
- || cacheControl.find(P_STATIC_STRING("private")) != string::npos)
585
+ || cacheControl.find(P_STATIC_STRING("private")) != string::npos
586
+ || cacheControl.find(P_STATIC_STRING("no-cache")) != string::npos)
575
587
  {
576
588
  return false;
577
589
  }
@@ -37,8 +37,8 @@ protected:
37
37
 
38
38
  virtual void execProgram() const {
39
39
  if (hasEnvOption("PASSENGER_RUN_HELPER_AGENT_IN_VALGRIND", false)) {
40
- execlp("valgrind", "valgrind", "--dsymutil=yes",
41
- agentFilename.c_str(), AGENT_EXE, "server",
40
+ execlp("valgrind", "valgrind", "--dsymutil=yes", "--track-origins=yes", "--leak-check=full",
41
+ agentFilename.c_str(), "server",
42
42
  // Some extra space to allow the child process to change its process title.
43
43
  " ", (char *) 0);
44
44
  } else {
@@ -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 = '5.0.5'
33
+ VERSION_STRING = '5.0.6'
34
34
 
35
35
  PREFERRED_NGINX_VERSION = '1.6.2'
36
36
  NGINX_SHA256_CHECKSUM = 'b5608c2959d3e7ad09b20fc8f9e5bd4bc87b3bc8ba5936a513c04ed8f1391a18'
@@ -1,5 +1,5 @@
1
1
  # Phusion Passenger - https://www.phusionpassenger.com/
2
- # Copyright (c) 2014 Phusion
2
+ # Copyright (c) 2014-2015 Phusion
3
3
  #
4
4
  # "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
5
5
  #
@@ -37,13 +37,13 @@ module PhusionPassenger
37
37
  include PhusionPassenger::Config::Utils
38
38
 
39
39
  def self.create_default_options
40
- return { :socket => "server_admin" }
40
+ return { :agent_name => "server_admin" }
41
41
  end
42
42
 
43
43
  def run
44
44
  parse_options
45
45
  initialize_objects
46
- select_passenger_instance
46
+ infer_socket_path_and_credentials
47
47
  invoke
48
48
  end
49
49
 
@@ -62,17 +62,22 @@ module PhusionPassenger
62
62
  opts.separator " METHOD is an HTTP verb, like 'GET', 'POST', 'PUT' or 'DELETE'."
63
63
  opts.separator " PATH is the admin URI. You can pass POST data with '-d'."
64
64
  opts.separator ""
65
- opts.separator " Example: passenger-config admin-command GET /server.json"
65
+ opts.separator " Example 1: passenger-config admin-command GET /server.json"
66
66
  opts.separator " Sends the 'GET /server.json' command to the HTTP server agent."
67
67
  opts.separator ""
68
- opts.separator " Example: passenger-config admin-command PUT /config.json \\"
69
- opts.separator " -d '{\"log_level\", 7}'"
68
+ opts.separator " Example 2: passenger-config admin-command PUT /config.json \\"
69
+ opts.separator " -d '{\"log_level\", 7}'"
70
70
  opts.separator " Sends the 'PUT /config.json' command to the HTTP server agent, with the"
71
71
  opts.separator " given PUT data."
72
72
  opts.separator ""
73
- opts.separator " Example: passenger-config admin-command POST /shutdown.json -a watchdog"
73
+ opts.separator " Example 3: passenger-config admin-command POST /shutdown.json -a watchdog"
74
74
  opts.separator " Sends the 'POST /shutdown.json' command to the watchdog, with no POST data."
75
75
  opts.separator ""
76
+ opts.separator " Example 4: passenger-config admin-command POST /shutdown.json \\"
77
+ opts.separator " -S /tmp/watchdog.sock"
78
+ opts.separator " Sends the 'POST /shutdown.json' command to the watchdog listening at the"
79
+ opts.separator " specific socket file /tmp/watchdog.sock. No POST data."
80
+ opts.separator ""
76
81
 
77
82
  opts.separator "Options:"
78
83
  opts.on("-d", "--data DATA", String, "Specify HTTP request body data") do |value|
@@ -90,12 +95,19 @@ module PhusionPassenger
90
95
  "is sent to. Choices: watchdog,#{nl}" +
91
96
  "server_admin, logging_admin.#{nl}" +
92
97
  "Default: server_admin") do |val|
93
- options[:socket] = val
98
+ options[:agent_name] = val
99
+ end
100
+ opts.on("-S", "--socket PATH", String, "Instead of inferring the socket path from#{nl}" +
101
+ "the #{PROGRAM_NAME} instance directory#{nl}" +
102
+ "and agent name, send the command to a#{nl}" +
103
+ "specific Unix domain socket directly") do |val|
104
+ options[:socket_path] = val
94
105
  end
95
106
  opts.on("--show-headers", "Show HTTP response headers") do
96
107
  options[:show_headers] = true
97
108
  end
98
- opts.on("--ignore-response-code", "Exit successfully even if a non-2xx response was returned") do
109
+ opts.on("--ignore-response-code", "Exit successfully even if a non-2xx#{nl}" +
110
+ "response was returned") do
99
111
  options[:ignore_response_code] = true
100
112
  end
101
113
  opts.on("--instance NAME", String, "The #{PROGRAM_NAME} instance to select") do |value|
@@ -144,15 +156,43 @@ module PhusionPassenger
144
156
  end
145
157
  end
146
158
 
159
+ def infer_socket_path_and_credentials
160
+ if @options[:socket_path]
161
+ @socket_path = @options[:socket_path]
162
+ else
163
+ select_passenger_instance
164
+ @socket_path = "#{@instance.path}/agents.s/#{@options[:agent_name]}"
165
+ @password = obtain_full_admin_password(@instance)
166
+ end
167
+ end
168
+
147
169
  def invoke
148
- password = obtain_full_admin_password(@instance)
149
- @request.basic_auth("admin", password)
170
+ if @password
171
+ @request.basic_auth("admin", @password)
172
+ end
150
173
  @request["connection"] = "close"
151
174
  if @options[:data]
152
175
  @request.content_type = "application/json"
153
176
  @request.body = @options[:data]
154
177
  end
155
- response = @instance.http_request("agents.s/#{@options[:socket]}", @request)
178
+
179
+ sock = Net::BufferedIO.new(UNIXSocket.new(@socket_path))
180
+ begin
181
+ @request.exec(sock, "1.1", @request.path)
182
+
183
+ done = false
184
+ while !done
185
+ response = Net::HTTPResponse.read_new(sock)
186
+ done = !response.kind_of?(Net::HTTPContinue)
187
+ end
188
+
189
+ response.reading_body(sock, @request.response_body_permitted?) do
190
+ # Nothing
191
+ end
192
+ ensure
193
+ sock.close
194
+ end
195
+
156
196
  if @options[:show_headers]
157
197
  print_headers(response)
158
198
  end