Skip to content

Commit

Permalink
Merge branch 'master' into 3.1
Browse files Browse the repository at this point in the history
Conflicts:
	ext/apache2/Bucket.cpp
	ext/apache2/Bucket.h
	ext/apache2/Hooks.cpp
  • Loading branch information
FooBarWidget committed Dec 20, 2011
2 parents 024a555 + 802b5a6 commit a30c1e3
Show file tree
Hide file tree
Showing 28 changed files with 342 additions and 105 deletions.
40 changes: 40 additions & 0 deletions NEWS
@@ -1,3 +1,43 @@
Release 3.0.11
--------------

* Fixed a compilation problem on platforms without alloca.h, such as FreeBSD 7.
* Improved performance and solved some warnings on Xen systems by compiling
with `-mno-tls-direct-seg-refs`. Patch contributed by Michał Pokrywka.


Release 3.0.10
--------------

* [Nginx] Dropped support for Nginx versions older than 1.0.0
* [Nginx] Fixed support for Nginx 1.1.4+
* [Nginx, Standalone] Upgraded default Nginx version to 1.0.10
The previously default version was 1.0.5.
* [Nginx] New option passenger_max_requests
This is equivalent to the PassengerMaxRequests option in the Apache
version: Phusion Passenger will automatically shutdown a worker process
once it has processed the specified number of requests.
Contributed by Paul Kmiec.
* [Apache] New option PassengerBufferResponse
The Apache version did not buffer responses. This could block the Ruby
worker process in case of slow clients. We now enable response buffering
by default. It can be turned off through this option. Feature contributed
by Ryo Onodera.
* Fixed remaining Ruby 1.9.3 compatibility problems
We already supported Ruby 1.9.3 since 3.0.8, but due to bugs in Ruby
1.9.3's build system Phusion Passenger would fail to detect Ruby 1.9.3
features on some systems. Fixes issue #714.
* Fixed a bug in PassengerPreStart
A regression was introduced in 3.0.8, causing the prespawn script to
connect to the host name instead of to 127.0.0.1. Fix contributed by
Andy Allan.
* Fixed compatibility with GCC 4.6
Affected systems include Ubuntu 11.10.
* Fixed various compilation problems.
* Fixed some Ruby 1.9 encoding problems.
* Fixed some Ruby 1.9.3 deprecation warnings.


Release 3.0.9
-------------

Expand Down
1 change: 1 addition & 0 deletions build/config.rb
Expand Up @@ -35,6 +35,7 @@
# Should be included last in the command string, even after PlatformInfo.portability_cflags.
EXTRA_CXXFLAGS = "-Wextra -Wno-unused-parameter -Wno-parentheses -Wpointer-arith -Wwrite-strings -Wno-long-long"
EXTRA_CXXFLAGS << " -Wno-missing-field-initializers" if PlatformInfo.compiler_supports_wno_missing_field_initializers_flag?
EXTRA_CXXFLAGS << " -mno-tls-direct-seg-refs" if PlatformInfo.requires_no_tls_direct_seg_refs? && PlatformInfo.compiler_supports_no_tls_direct_seg_refs_option?
EXTRA_CXXFLAGS << " #{OPTIMIZATION_FLAGS}" if !OPTIMIZATION_FLAGS.empty?

# Extra linker flags that should always be passed to the linker.
Expand Down
64 changes: 64 additions & 0 deletions doc/Users guide Apache.txt
Expand Up @@ -923,6 +923,70 @@ allow the attacker to cause a Denial-of-Service.
You can prevent this from happening by pointing PassengerRestartDir to a
directory that's readable by Apache, but only writable by administrators.

[[PassengerBufferResponse]]
=== PassengerBufferResponse <on|off> ===
When turned on, application-generated responses are buffered in memory. By buffering
responses, protection is provided against slow HTTP clients that can not read your
response immediately.

For example, consider an HTTP client that's on a dial-up modem link, and your
application instance generates a 2 MB response. If response buffering is turned
off then your application instance will be blocked until the entire 2 MB has been
sent out to the HTTP client. This disallows your application instance to do any useful
work in the mean time. By enabling response buffering, Phusion Passenger will read
the application response as quickly as possible and will take care of slow clients.

However, keep in mind that enabling this option will make streaming responses
impossible. Consider for example this piece of Rails code:

--------------------------------
render :text => lambda { |response, output|
10.times do |i|
output.write("entry #{i}\n")
output.flush
sleep 1
end
}
--------------------------------

...or this piece of Rack code:

--------------------------------
class Response
def each
10.times do |i|
yield("entry #{i}\n")
sleep 1
end
end
end

app = lambda do |env|
[200, { "Content-Type" => "text/plain" }, Response.new]
end
--------------------------------

When response buffering is turned on, Phusion Passenger will wait until
the application is done sending the entire response before forwarding it
to the client. The client will not receive anything for 10 seconds,
after which it receives the entire response at once.
When response buffering is turned off, it works as expected: the client
receives an "entry X" message every second for 10 seconds.

This option may occur in the following places:

* In the global server configuration.
* In a virtual host configuration block.
* In a `<Directory>` or `<Location>` block.
* In '.htaccess'.

In each place, it may be specified at most once. The default value is 'on'.

[NOTE]
=====================================================
The <<PassengerBufferResponse,PassengerBufferResponse>> directive should be turned off
if responses can be huge. Because entire responses are buffered in memory when turned on.
=====================================================

=== Security options ===

Expand Down
12 changes: 7 additions & 5 deletions ext/apache2/Bucket.cpp
Expand Up @@ -45,6 +45,7 @@ static const apr_bucket_type_t apr_bucket_type_passenger_pipe = {
struct BucketData {
FileDescriptor fd;
PassengerBucketStatePtr state;
bool bufferResponse;
};

static void
Expand All @@ -65,7 +66,7 @@ bucket_read(apr_bucket *bucket, const char **str, apr_size_t *len, apr_read_type
*str = NULL;
*len = 0;

if (block == APR_NONBLOCK_READ) {
if (!data->bufferResponse && block == APR_NONBLOCK_READ) {
/*
* The bucket brigade that Hooks::handleRequest() passes using
* ap_pass_brigade() is always passed through ap_content_length_filter,
Expand Down Expand Up @@ -115,7 +116,7 @@ bucket_read(apr_bucket *bucket, const char **str, apr_size_t *len, apr_read_type
* which can read the next chunk from the stream.
*/
APR_BUCKET_INSERT_AFTER(bucket, passenger_bucket_create(
data->state, bucket->list));
data->state, bucket->list, data->bufferResponse));

/* The newly created Passenger Bucket has a reference to the session
* object, so we can delete data here.
Expand Down Expand Up @@ -148,9 +149,10 @@ bucket_read(apr_bucket *bucket, const char **str, apr_size_t *len, apr_read_type
}

static apr_bucket *
passenger_bucket_make(apr_bucket *bucket, const PassengerBucketStatePtr &state) {
passenger_bucket_make(apr_bucket *bucket, const PassengerBucketStatePtr &state, bool bufferResponse) {
BucketData *data = new BucketData();
data->state = state;
data->bufferResponse = bufferResponse;

bucket->type = &apr_bucket_type_passenger_pipe;
bucket->length = (apr_size_t)(-1);
Expand All @@ -160,14 +162,14 @@ passenger_bucket_make(apr_bucket *bucket, const PassengerBucketStatePtr &state)
}

apr_bucket *
passenger_bucket_create(const PassengerBucketStatePtr &state, apr_bucket_alloc_t *list) {
passenger_bucket_create(const PassengerBucketStatePtr &state, apr_bucket_alloc_t *list, bool bufferResponse) {
apr_bucket *bucket;

bucket = (apr_bucket *) apr_bucket_alloc(sizeof(*bucket), list);
APR_BUCKET_INIT(bucket);
bucket->free = apr_bucket_free;
bucket->list = list;
return passenger_bucket_make(bucket, state);
return passenger_bucket_make(bucket, state, bufferResponse);
}

} // namespace Passenger
3 changes: 2 additions & 1 deletion ext/apache2/Bucket.h
Expand Up @@ -83,7 +83,8 @@ typedef shared_ptr<PassengerBucketState> PassengerBucketStatePtr;
* - It can store its current state in a PassengerBucketState data structure.
*/
apr_bucket *passenger_bucket_create(const PassengerBucketStatePtr &state,
apr_bucket_alloc_t *list);
apr_bucket_alloc_t *list,
bool bufferResponse);

} // namespace Passenger

Expand Down
8 changes: 8 additions & 0 deletions ext/apache2/Configuration.cpp
Expand Up @@ -209,6 +209,7 @@ passenger_config_create_dir(apr_pool_t *p, char *dirspec) {
config->uploadBufferDir = NULL;
config->friendlyErrorPages = DirConfig::UNSET;
config->unionStationSupport = DirConfig::UNSET;
config->bufferResponse = DirConfig::UNSET;
/*************************************/
return config;
}
Expand Down Expand Up @@ -259,6 +260,7 @@ passenger_config_merge_dir(apr_pool_t *p, void *basev, void *addv) {
MERGE_THREEWAY_CONFIG(allowEncodedSlashes);
MERGE_THREEWAY_CONFIG(friendlyErrorPages);
MERGE_THREEWAY_CONFIG(unionStationSupport);
MERGE_THREEWAY_CONFIG(bufferResponse);
/*************************************/
return config;
}
Expand Down Expand Up @@ -313,6 +315,7 @@ DEFINE_DIR_THREEWAY_CONFIG_SETTER(cmd_passenger_resolve_symlinks_in_document_roo
DEFINE_DIR_THREEWAY_CONFIG_SETTER(cmd_passenger_allow_encoded_slashes, allowEncodedSlashes)
DEFINE_DIR_THREEWAY_CONFIG_SETTER(cmd_passenger_friendly_error_pages, friendlyErrorPages)
DEFINE_DIR_THREEWAY_CONFIG_SETTER(cmd_union_station_support, unionStationSupport)
DEFINE_DIR_THREEWAY_CONFIG_SETTER(cmd_passenger_buffer_response, bufferResponse)

static const char *
cmd_passenger_spawn_method(cmd_parms *cmd, void *pcfg, const char *arg) {
Expand Down Expand Up @@ -586,6 +589,11 @@ const command_rec passenger_commands[] = {
NULL,
OR_ALL,
"A filter for Union Station data."),
AP_INIT_FLAG("PassengerBufferResponse",
(FlagFunc) cmd_passenger_buffer_response,
NULL,
OR_ALL,
"Whether to enable buffering response."),
AP_INIT_FLAG("PassengerResolveSymlinksInDocumentRoot",
(FlagFunc) cmd_passenger_resolve_symlinks_in_document_root,
NULL,
Expand Down
9 changes: 9 additions & 0 deletions ext/apache2/Configuration.hpp
Expand Up @@ -192,6 +192,11 @@ struct DirConfig {
*/
Threeway unionStationSupport;

/**
* Whether response buffering support is enabled.
*/
Threeway bufferResponse;

/*************************************/
/*************************************/

Expand Down Expand Up @@ -315,6 +320,10 @@ struct DirConfig {
bool useUnionStation() const {
return unionStationSupport == ENABLED;
}

bool getBufferResponse() const {
return bufferResponse != DISABLED;
}

string getUnionStationFilterString() const {
if (unionStationFilters.empty()) {
Expand Down
2 changes: 1 addition & 1 deletion ext/apache2/Hooks.cpp
Expand Up @@ -589,7 +589,7 @@ class Hooks {
bb = apr_brigade_create(r->connection->pool, r->connection->bucket_alloc);

bucketState = make_shared<PassengerBucketState>(conn);
b = passenger_bucket_create(bucketState, r->connection->bucket_alloc);
b = passenger_bucket_create(bucketState, r->connection->bucket_alloc, config->getBufferResponse());
APR_BRIGADE_INSERT_TAIL(bb, b);

b = apr_bucket_eos_create(r->connection->bucket_alloc);
Expand Down
2 changes: 1 addition & 1 deletion ext/common/Constants.h
Expand Up @@ -26,7 +26,7 @@
#define _PASSENGER_CONSTANTS_H_

/* Don't forget to update lib/phusion_passenger.rb too. */
#define PASSENGER_VERSION "3.0.9"
#define PASSENGER_VERSION "3.0.11"

#define FEEDBACK_FD 3

Expand Down
6 changes: 4 additions & 2 deletions ext/common/EventedMessageServer.h
@@ -1,6 +1,6 @@
/*
* Phusion Passenger - http://www.modrails.com/
* Copyright (c) 2010 Phusion
* Copyright (c) 2010, 2011 Phusion
*
* "Phusion Passenger" is a trademark of Hongli Lai & Ninh Bui.
*
Expand Down Expand Up @@ -29,7 +29,9 @@
#include <ev++.h>
#include <cstdarg>
#include <cstdlib>
#include <alloca.h>
#ifdef HAS_ALLOCA_H_
#include <alloca.h>
#endif
#include "EventedServer.h"
#include "MessageReadersWriters.h"
#include "AccountsDatabase.h"
Expand Down
11 changes: 5 additions & 6 deletions ext/common/FileDescriptor.h
Expand Up @@ -42,7 +42,10 @@ using namespace boost;
using namespace oxt;


void safelyClose(int fd);
#ifndef _PASSENGER_SAFELY_CLOSE_DEFINED_
#define _PASSENGER_SAFELY_CLOSE_DEFINED_
void safelyClose(int fd, bool ignoreErrors = false);
#endif


/**
Expand Down Expand Up @@ -81,11 +84,7 @@ class FileDescriptor {
this_thread::disable_syscall_interruption dsi;
int theFd = fd;
fd = -1;
if (checkErrors) {
safelyClose(theFd);
} else {
syscalls::close(fd);
}
safelyClose(theFd, !checkErrors);
}
}

Expand Down
8 changes: 4 additions & 4 deletions ext/common/IniFile.h
Expand Up @@ -176,7 +176,7 @@ class IniFileLexer {
}

void accept() {
if (upcomingChar == EOF) return;
if ((int) upcomingChar == EOF) return;

lastAcceptedChar = (char)iniFileStream.get();
upcomingChar = (char)iniFileStream.peek();
Expand All @@ -189,7 +189,7 @@ class IniFileLexer {
}

void ignore() {
if (upcomingChar == EOF) return;
if ((int) upcomingChar == EOF) return;

upcomingChar = (char)iniFileStream.peek();
currentColumn++;
Expand Down Expand Up @@ -261,7 +261,7 @@ class IniFileLexer {
int column = currentColumn;
string result;

while (upcomingChar != '\n' && upcomingChar != EOF) {
while (upcomingChar != '\n' && (int) upcomingChar != EOF) {
result.append(1, upcomingChar);
accept();
}
Expand All @@ -282,7 +282,7 @@ class IniFileLexer {
int column = currentColumn;
string result;

while (upcomingChar != EOF) {
while ((int) upcomingChar != EOF) {
result.append(1, upcomingChar);
accept();
}
Expand Down
5 changes: 2 additions & 3 deletions ext/common/Process.h
Expand Up @@ -41,6 +41,7 @@
#include <Exceptions.h>
#include <Logging.h>
#include <Utils.h>
#include <Utils/IOUtils.h>

namespace Passenger {

Expand Down Expand Up @@ -123,9 +124,7 @@ class Process {
int ret;

if (ownerPipe != -1) {
do {
ret = close(ownerPipe);
} while (ret == -1 && errno == EINTR);
safelyClose(ownerPipe, true);
}
for (it = serverSockets.begin(); it != serverSockets.end(); it++) {
const SocketInfo &info = it->second;
Expand Down

0 comments on commit a30c1e3

Please sign in to comment.