passenger 5.0.26 → 5.0.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of passenger might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG +17 -0
- data/CONTRIBUTORS +1 -0
- data/build/cxx_dependency_map.rb +113 -157
- data/build/cxx_tests.rb +8 -1
- data/src/agent/Core/ApplicationPool/TestSession.h +5 -1
- data/src/agent/Core/Controller/CheckoutSession.cpp +1 -1
- data/src/agent/Core/Controller/ForwardResponse.cpp +9 -0
- data/src/agent/Core/Controller/InternalUtils.cpp +9 -1
- data/src/agent/Core/Controller/SendRequest.cpp +13 -7
- data/src/agent/Core/Controller/StateInspectionAndConfiguration.cpp +3 -2
- data/src/agent/Core/CoreMain.cpp +3 -0
- data/src/agent/Core/SpawningKit/SmartSpawner.h +1 -1
- data/src/agent/Core/SpawningKit/Spawner.h +2 -2
- data/src/agent/Core/UnionStation/StopwatchLog.h +3 -4
- data/src/agent/Shared/Base.cpp +32 -0
- data/src/agent/Shared/Base.h +2 -0
- data/src/agent/UstRouter/UstRouterMain.cpp +3 -0
- data/src/agent/Watchdog/AgentWatcher.cpp +1 -3
- data/src/agent/Watchdog/WatchdogMain.cpp +31 -6
- data/src/apache2_module/Hooks.cpp +2 -2
- data/src/cxx_supportlib/BackgroundEventLoop.cpp +12 -2
- data/src/cxx_supportlib/Constants.h +1 -1
- data/src/cxx_supportlib/DataStructures/LString.cpp +39 -0
- data/src/cxx_supportlib/DataStructures/LString.h +35 -6
- data/src/cxx_supportlib/FileDescriptor.h +3 -1
- data/src/cxx_supportlib/Integrations/LibevJsonUtils.h +92 -0
- data/src/cxx_supportlib/ResourceLocator.h +10 -8
- data/src/cxx_supportlib/ServerKit/CookieUtils.h +4 -0
- data/src/cxx_supportlib/ServerKit/FileBufferedChannel.h +2 -0
- data/src/cxx_supportlib/ServerKit/HttpServer.h +6 -2
- data/src/cxx_supportlib/Utils.cpp +4 -5
- data/src/cxx_supportlib/Utils.h +2 -2
- data/src/cxx_supportlib/Utils/IOUtils.cpp +1 -1
- data/src/cxx_supportlib/Utils/JsonUtils.h +12 -10
- data/src/cxx_supportlib/Utils/MessagePassing.h +4 -4
- data/src/cxx_supportlib/Utils/StrIntUtils.cpp +7 -3
- data/src/cxx_supportlib/Utils/SystemTime.cpp +15 -4
- data/src/cxx_supportlib/Utils/SystemTime.h +228 -54
- data/src/cxx_supportlib/Utils/Timer.h +14 -41
- data/src/cxx_supportlib/WatchdogLauncher.h +1 -1
- data/src/cxx_supportlib/vendor-copy/libuv/Makefile.in +198 -59
- data/src/cxx_supportlib/vendor-copy/libuv/autom4te.cache/output.0 +15477 -0
- data/src/cxx_supportlib/vendor-copy/libuv/autom4te.cache/output.1 +15477 -0
- data/src/cxx_supportlib/vendor-copy/libuv/autom4te.cache/requests +324 -0
- data/src/cxx_supportlib/vendor-copy/libuv/autom4te.cache/traces.0 +3105 -0
- data/src/cxx_supportlib/vendor-copy/libuv/autom4te.cache/traces.1 +703 -0
- data/src/cxx_supportlib/vendor-copy/libuv/configure +115 -12
- data/src/cxx_supportlib/vendor-copy/libuv/ltmain.sh +15 -8
- data/src/cxx_supportlib/vendor-copy/libuv/m4/ltversion.m4 +5 -5
- data/src/cxx_supportlib/vendor-modified/psg_sysqueue.h +1 -0
- data/src/nginx_module/ngx_http_passenger_module.c +1 -1
- data/src/nodejs_supportlib/phusion_passenger/ustreporter.js +1 -1
- data/src/ruby_native_extension/passenger_native_support.c +1 -1
- data/src/ruby_supportlib/phusion_passenger.rb +15 -1
- data/src/ruby_supportlib/phusion_passenger/common_library.rb +4 -0
- data/src/ruby_supportlib/phusion_passenger/packaging.rb +1 -0
- data/src/ruby_supportlib/phusion_passenger/ruby_core_io_enhancements.rb +5 -20
- metadata +9 -2
    
        data/build/cxx_tests.rb
    CHANGED
    
    | @@ -198,7 +198,14 @@ task 'test:cxx' => dependencies do | |
| 198 198 | 
             
              if boolean_option('GDB')
         | 
| 199 199 | 
             
                command = "gdb --args #{command}"
         | 
| 200 200 | 
             
              elsif boolean_option('VALGRIND')
         | 
| 201 | 
            -
                 | 
| 201 | 
            +
                valgrind_args = "--dsymutil=yes --vgdb=yes --vgdb-error=1 --child-silent-after-fork=yes"
         | 
| 202 | 
            +
                if boolean_option('LEAK_CHECK')
         | 
| 203 | 
            +
                  valgrind_args << " --leak-check=yes"
         | 
| 204 | 
            +
                end
         | 
| 205 | 
            +
                if RUBY_PLATFORM =~ /darwin/
         | 
| 206 | 
            +
                  valgrind_args << " --suppressions=valgrind-osx.supp"
         | 
| 207 | 
            +
                end
         | 
| 208 | 
            +
                command = "valgrind #{valgrind_args} #{command}"
         | 
| 202 209 | 
             
              end
         | 
| 203 210 | 
             
              if boolean_option('SUDO')
         | 
| 204 211 | 
             
                command = "#{PlatformInfo.ruby_sudo_command} #{command}"
         | 
| @@ -38,7 +38,11 @@ namespace ApplicationPool2 { | |
| 38 38 |  | 
| 39 39 | 
             
            using namespace std;
         | 
| 40 40 |  | 
| 41 | 
            -
             | 
| 41 | 
            +
            /**
         | 
| 42 | 
            +
             * The TestSession represents a session between the Core to the Application. There is a
         | 
| 43 | 
            +
             * connection between the two, which is represented by a SocketPair having a first (Core side)
         | 
| 44 | 
            +
             * and second (Application side) FD. These are also referred to as fd and peerFd.
         | 
| 45 | 
            +
             */
         | 
| 42 46 | 
             
            class TestSession: public AbstractSession {
         | 
| 43 47 | 
             
            private:
         | 
| 44 48 | 
             
            	mutable boost::mutex syncher;
         | 
| @@ -64,7 +64,7 @@ Controller::checkoutSession(Client *client, Request *req) { | |
| 64 64 | 
             
            	callback.func = sessionCheckedOut;
         | 
| 65 65 | 
             
            	callback.userData = req;
         | 
| 66 66 |  | 
| 67 | 
            -
            	options.currentTime = ( | 
| 67 | 
            +
            	options.currentTime = SystemTime::getUsec();
         | 
| 68 68 |  | 
| 69 69 | 
             
            	refRequest(req, __FILE__, __LINE__);
         | 
| 70 70 | 
             
            	#ifdef DEBUG_CC_EVENT_LOOP_BLOCKING
         | 
| @@ -822,6 +822,7 @@ Controller::sendResponseHeaderWithWritev(Client *client, Request *req, | |
| 822 822 | 
             
            	if (constructHeaderBuffersForResponse(req, buffers,
         | 
| 823 823 | 
             
            		maxbuffers, nbuffers, dataSize, nCacheableBuffers))
         | 
| 824 824 | 
             
            	{
         | 
| 825 | 
            +
            		UPDATE_TRACE_POINT();
         | 
| 825 826 | 
             
            		SKC_TRACE(client, 2, "Sending response headers using writev()");
         | 
| 826 827 | 
             
            		logResponseHeaders(client, req, buffers, nbuffers, dataSize);
         | 
| 827 828 | 
             
            		markHeaderBuffersForTurboCaching(client, req, buffers, nCacheableBuffers);
         | 
| @@ -834,6 +835,7 @@ Controller::sendResponseHeaderWithWritev(Client *client, Request *req, | |
| 834 835 | 
             
            		req->responseBegun |= ret > 0;
         | 
| 835 836 | 
             
            		return ret == (ssize_t) dataSize;
         | 
| 836 837 | 
             
            	} else {
         | 
| 838 | 
            +
            		UPDATE_TRACE_POINT();
         | 
| 837 839 | 
             
            		bytesWritten = 0;
         | 
| 838 840 | 
             
            		return false;
         | 
| 839 841 | 
             
            	}
         | 
| @@ -843,6 +845,7 @@ void | |
| 843 845 | 
             
            Controller::sendResponseHeaderWithBuffering(Client *client, Request *req,
         | 
| 844 846 | 
             
            	unsigned int offset)
         | 
| 845 847 | 
             
            {
         | 
| 848 | 
            +
            	TRACE_POINT();
         | 
| 846 849 | 
             
            	struct iovec *buffers;
         | 
| 847 850 | 
             
            	unsigned int nbuffers, dataSize, nCacheableBuffers;
         | 
| 848 851 | 
             
            	bool ok;
         | 
| @@ -858,18 +861,21 @@ Controller::sendResponseHeaderWithBuffering(Client *client, Request *req, | |
| 858 861 | 
             
            	assert(ok);
         | 
| 859 862 | 
             
            	(void) ok; // Shut up compiler warning
         | 
| 860 863 |  | 
| 864 | 
            +
            	UPDATE_TRACE_POINT();
         | 
| 861 865 | 
             
            	logResponseHeaders(client, req, buffers, nbuffers, dataSize);
         | 
| 862 866 | 
             
            	markHeaderBuffersForTurboCaching(client, req, buffers, nCacheableBuffers);
         | 
| 863 867 |  | 
| 864 868 | 
             
            	MemoryKit::mbuf_pool &mbuf_pool = getContext()->mbuf_pool;
         | 
| 865 869 | 
             
            	const unsigned int MBUF_MAX_SIZE = mbuf_pool_data_size(&mbuf_pool);
         | 
| 866 870 | 
             
            	if (dataSize <= MBUF_MAX_SIZE) {
         | 
| 871 | 
            +
            		UPDATE_TRACE_POINT();
         | 
| 867 872 | 
             
            		SKC_TRACE(client, 2, "Sending response headers using an mbuf");
         | 
| 868 873 | 
             
            		MemoryKit::mbuf buffer(MemoryKit::mbuf_get(&mbuf_pool));
         | 
| 869 874 | 
             
            		gatherBuffers(buffer.start, MBUF_MAX_SIZE, buffers, nbuffers);
         | 
| 870 875 | 
             
            		buffer = MemoryKit::mbuf(buffer, offset, dataSize - offset);
         | 
| 871 876 | 
             
            		writeResponse(client, buffer);
         | 
| 872 877 | 
             
            	} else {
         | 
| 878 | 
            +
            		UPDATE_TRACE_POINT();
         | 
| 873 879 | 
             
            		SKC_TRACE(client, 2, "Sending response headers using a psg_pool buffer");
         | 
| 874 880 | 
             
            		char *buffer = (char *) psg_pnalloc(req->pool, dataSize);
         | 
| 875 881 | 
             
            		gatherBuffers(buffer, dataSize, buffers, nbuffers);
         | 
| @@ -882,6 +888,7 @@ Controller::logResponseHeaders(Client *client, Request *req, struct iovec *buffe | |
| 882 888 | 
             
            	unsigned int nbuffers, unsigned int dataSize)
         | 
| 883 889 | 
             
            {
         | 
| 884 890 | 
             
            	if (OXT_UNLIKELY(getLogLevel() >= LVL_DEBUG3)) {
         | 
| 891 | 
            +
            		TRACE_POINT();
         | 
| 885 892 | 
             
            		char *buffer = (char *) psg_pnalloc(req->pool, dataSize);
         | 
| 886 893 | 
             
            		gatherBuffers(buffer, dataSize, buffers, nbuffers);
         | 
| 887 894 | 
             
            		SKC_TRACE(client, 3, "Sending response headers: \"" <<
         | 
| @@ -889,6 +896,7 @@ Controller::logResponseHeaders(Client *client, Request *req, struct iovec *buffe | |
| 889 896 | 
             
            	}
         | 
| 890 897 |  | 
| 891 898 | 
             
            	if (req->useUnionStation()) {
         | 
| 899 | 
            +
            		TRACE_POINT();
         | 
| 892 900 | 
             
            		const char *status = getStatusCodeAndReasonPhrase(req->appResponse.statusCode);
         | 
| 893 901 | 
             
            		if (status != NULL) {
         | 
| 894 902 | 
             
            			req->logMessage("Status: " + StaticString(status));
         | 
| @@ -899,6 +907,7 @@ Controller::logResponseHeaders(Client *client, Request *req, struct iovec *buffe | |
| 899 907 | 
             
            		if (req->appResponse.statusCode >= 400 && req->appResponse.statusCode <= 599) {
         | 
| 900 908 | 
             
            			// Log the request headers like Request headers: { header1: values1-concatenated, header2: values2-concatenated } (single line)
         | 
| 901 909 | 
             
            			// Concatenation was already done by HeaderTable.h:insert (using a comma ',' for joining, or a semicolon ';' for Cookie headers
         | 
| 910 | 
            +
            			UPDATE_TRACE_POINT();
         | 
| 902 911 | 
             
            			ServerKit::HeaderTable::Iterator it(req->headers);
         | 
| 903 912 | 
             
            			Json::Value json;
         | 
| 904 913 | 
             
            			while (*it != NULL) {
         | 
| @@ -102,7 +102,15 @@ Controller::disconnectWithAppSocketWriteError(Client **client, int e) { | |
| 102 102 | 
             
            void
         | 
| 103 103 | 
             
            Controller::endRequestWithAppSocketIncompleteResponse(Client **client, Request **req) {
         | 
| 104 104 | 
             
            	if (!(*req)->responseBegun) {
         | 
| 105 | 
            -
            		 | 
| 105 | 
            +
            		// The application might have decided to abort the response because it thinks the client
         | 
| 106 | 
            +
            		// is already gone (Passenger relays socket half-close events from clients), so don't
         | 
| 107 | 
            +
            		// make a big warning out of that situation.
         | 
| 108 | 
            +
            		if ((*req)->halfClosePolicy == Request::HALF_CLOSE_PERFORMED) {
         | 
| 109 | 
            +
            			SKC_DEBUG(*client, "Sending 502 response: application did not send a complete response"
         | 
| 110 | 
            +
            				" (likely because client half-closed)");
         | 
| 111 | 
            +
            		} else {
         | 
| 112 | 
            +
            			SKC_WARN(*client, "Sending 502 response: application did not send a complete response");
         | 
| 113 | 
            +
            		}
         | 
| 106 114 | 
             
            		endRequestWithSimpleResponse(client, req,
         | 
| 107 115 | 
             
            			"<h2>Incomplete response received from application</h2>", 502);
         | 
| 108 116 | 
             
            	} else {
         | 
| @@ -24,9 +24,7 @@ | |
| 24 24 | 
             
             *  THE SOFTWARE.
         | 
| 25 25 | 
             
             */
         | 
| 26 26 | 
             
            #include <Core/Controller.h>
         | 
| 27 | 
            -
             | 
| 28 | 
            -
            // For calculating delta_monotonic (Ruby < 2.1 workaround, otherwise unused)
         | 
| 29 | 
            -
            #include <uv.h>
         | 
| 27 | 
            +
            #include <Utils/SystemTime.h>
         | 
| 30 28 |  | 
| 31 29 | 
             
            /*************************************************************************
         | 
| 32 30 | 
             
             *
         | 
| @@ -159,10 +157,18 @@ Controller::sendHeaderToAppWithSessionProtocol(Client *client, Request *req) { | |
| 159 157 | 
             
            	SessionProtocolWorkingState state;
         | 
| 160 158 |  | 
| 161 159 | 
             
            	// Workaround for Ruby < 2.1 support.
         | 
| 162 | 
            -
            	std::string  | 
| 160 | 
            +
            	std::string deltaMonotonic;
         | 
| 161 | 
            +
            	unsigned long long now = SystemTime::getUsec();
         | 
| 162 | 
            +
            	MonotonicTimeUsec monotonicNow = SystemTime::getMonotonicUsec();
         | 
| 163 | 
            +
            	if (now > monotonicNow) {
         | 
| 164 | 
            +
            		deltaMonotonic = boost::to_string(now - monotonicNow);
         | 
| 165 | 
            +
            	} else {
         | 
| 166 | 
            +
            		long long diff = monotonicNow - now;
         | 
| 167 | 
            +
            		deltaMonotonic = boost::to_string(-diff);
         | 
| 168 | 
            +
            	}
         | 
| 163 169 |  | 
| 164 170 | 
             
            	unsigned int bufferSize = determineHeaderSizeForSessionProtocol(req,
         | 
| 165 | 
            -
            		state,  | 
| 171 | 
            +
            		state, deltaMonotonic);
         | 
| 166 172 | 
             
            	MemoryKit::mbuf_pool &mbuf_pool = getContext()->mbuf_pool;
         | 
| 167 173 | 
             
            	const unsigned int MBUF_MAX_SIZE = mbuf_pool_data_size(&mbuf_pool);
         | 
| 168 174 | 
             
            	bool ok;
         | 
| @@ -172,7 +178,7 @@ Controller::sendHeaderToAppWithSessionProtocol(Client *client, Request *req) { | |
| 172 178 | 
             
            		bufferSize = MBUF_MAX_SIZE;
         | 
| 173 179 |  | 
| 174 180 | 
             
            		ok = constructHeaderForSessionProtocol(req, buffer.start,
         | 
| 175 | 
            -
            			bufferSize, state,  | 
| 181 | 
            +
            			bufferSize, state, deltaMonotonic);
         | 
| 176 182 | 
             
            		assert(ok);
         | 
| 177 183 | 
             
            		buffer = MemoryKit::mbuf(buffer, 0, bufferSize);
         | 
| 178 184 | 
             
            		SKC_TRACE(client, 3, "Header data: \"" << cEscapeString(
         | 
| @@ -182,7 +188,7 @@ Controller::sendHeaderToAppWithSessionProtocol(Client *client, Request *req) { | |
| 182 188 | 
             
            		char *buffer = (char *) psg_pnalloc(req->pool, bufferSize);
         | 
| 183 189 |  | 
| 184 190 | 
             
            		ok = constructHeaderForSessionProtocol(req, buffer,
         | 
| 185 | 
            -
            			bufferSize, state,  | 
| 191 | 
            +
            			bufferSize, state, deltaMonotonic);
         | 
| 186 192 | 
             
            		assert(ok);
         | 
| 187 193 | 
             
            		SKC_TRACE(client, 3, "Header data: \"" << cEscapeString(
         | 
| 188 194 | 
             
            			StaticString(buffer, bufferSize)) << "\"");
         | 
| @@ -24,6 +24,7 @@ | |
| 24 24 | 
             
             *  THE SOFTWARE.
         | 
| 25 25 | 
             
             */
         | 
| 26 26 | 
             
            #include <Core/Controller.h>
         | 
| 27 | 
            +
            #include <Integrations/LibevJsonUtils.h>
         | 
| 27 28 |  | 
| 28 29 | 
             
            /*************************************************************************
         | 
| 29 30 | 
             
             *
         | 
| @@ -86,7 +87,7 @@ Controller::inspectStateAsJson() const { | |
| 86 87 | 
             
            Json::Value
         | 
| 87 88 | 
             
            Controller::inspectClientStateAsJson(const Client *client) const {
         | 
| 88 89 | 
             
            	Json::Value doc = ParentClass::inspectClientStateAsJson(client);
         | 
| 89 | 
            -
            	doc["connected_at"] =  | 
| 90 | 
            +
            	doc["connected_at"] = evTimeToJson(client->connectedAt, ev_now(getLoop()));
         | 
| 90 91 | 
             
            	return doc;
         | 
| 91 92 | 
             
            }
         | 
| 92 93 |  | 
| @@ -97,7 +98,7 @@ Controller::inspectRequestStateAsJson(const Request *req) const { | |
| 97 98 | 
             
            	const AppResponse *resp = &req->appResponse;
         | 
| 98 99 |  | 
| 99 100 | 
             
            	if (req->startedAt != 0) {
         | 
| 100 | 
            -
            		doc["started_at"] =  | 
| 101 | 
            +
            		doc["started_at"] = evTimeToJson(req->startedAt, ev_now(getLoop()));
         | 
| 101 102 | 
             
            	}
         | 
| 102 103 | 
             
            	doc["state"] = req->getStateString();
         | 
| 103 104 | 
             
            	if (req->stickySession) {
         | 
    
        data/src/agent/Core/CoreMain.cpp
    CHANGED
    
    
| @@ -344,7 +344,7 @@ private: | |
| 344 344 | 
             
            		try {
         | 
| 345 345 | 
             
            			const size_t UNIX_PATH_MAX = sizeof(((struct sockaddr_un *) 0)->sun_path);
         | 
| 346 346 | 
             
            			string data = "You have control 1.0\n"
         | 
| 347 | 
            -
            				"passenger_root: " + config->resourceLocator-> | 
| 347 | 
            +
            				"passenger_root: " + config->resourceLocator->getInstallSpec() + "\n"
         | 
| 348 348 | 
             
            				"ruby_libdir: " + config->resourceLocator->getRubyLibDir() + "\n"
         | 
| 349 349 | 
             
            				"passenger_version: " PASSENGER_VERSION "\n"
         | 
| 350 350 | 
             
            				"UNIX_PATH_MAX: " + toString(UNIX_PATH_MAX) + "\n";
         | 
| @@ -270,7 +270,7 @@ private: | |
| 270 270 | 
             
            		try {
         | 
| 271 271 | 
             
            			const size_t UNIX_PATH_MAX = sizeof(((struct sockaddr_un *) 0)->sun_path);
         | 
| 272 272 | 
             
            			string data = "You have control 1.0\n"
         | 
| 273 | 
            -
            				"passenger_root: " + config->resourceLocator-> | 
| 273 | 
            +
            				"passenger_root: " + config->resourceLocator->getInstallSpec() + "\n"
         | 
| 274 274 | 
             
            				"passenger_version: " PASSENGER_VERSION "\n"
         | 
| 275 275 | 
             
            				"ruby_libdir: " + config->resourceLocator->getRubyLibDir() + "\n"
         | 
| 276 276 | 
             
            				"gupid: " + details.gupid + "\n"
         | 
| @@ -461,7 +461,7 @@ protected: | |
| 461 461 | 
             
            	 * <em>timeout</em> miliseconds for the process to exit.
         | 
| 462 462 | 
             
            	 */
         | 
| 463 463 | 
             
            	static int timedWaitpid(pid_t pid, int *status, unsigned long long timeout) {
         | 
| 464 | 
            -
            		Timer timer;
         | 
| 464 | 
            +
            		Timer<SystemTime::GRAN_10MSEC> timer;
         | 
| 465 465 | 
             
            		int ret;
         | 
| 466 466 |  | 
| 467 467 | 
             
            		do {
         | 
| @@ -1,6 +1,6 @@ | |
| 1 1 | 
             
            /*
         | 
| 2 2 | 
             
             *  Phusion Passenger - https://www.phusionpassenger.com/
         | 
| 3 | 
            -
             *  Copyright (c) 2010- | 
| 3 | 
            +
             *  Copyright (c) 2010-2016 Phusion Holding B.V.
         | 
| 4 4 | 
             
             *
         | 
| 5 5 | 
             
             *  "Passenger", "Phusion Passenger" and "Union Station" are registered
         | 
| 6 6 | 
             
             *  trademarks of Phusion Holding B.V.
         | 
| @@ -32,7 +32,6 @@ | |
| 32 32 |  | 
| 33 33 | 
             
            #include <string>
         | 
| 34 34 |  | 
| 35 | 
            -
            #include <uv.h>
         | 
| 36 35 | 
             
            #include <StaticString.h>
         | 
| 37 36 | 
             
            #include <Exceptions.h>
         | 
| 38 37 | 
             
            #include <Utils/StrIntUtils.h>
         | 
| @@ -82,7 +81,7 @@ public: | |
| 82 81 | 
             
            		pos = appendData(pos, end, "BEGIN: ");
         | 
| 83 82 | 
             
            		pos = appendData(pos, end, id);
         | 
| 84 83 | 
             
            		pos = appendData(pos, end, " (");
         | 
| 85 | 
            -
            		pos = appendData(pos, end, usecToString( | 
| 84 | 
            +
            		pos = appendData(pos, end, usecToString(SystemTime::getMonotonicUsec()));
         | 
| 86 85 | 
             
            		pos = appendData(pos, end, ",");
         | 
| 87 86 | 
             
            		if (getrusage(RUSAGE_SELF, &usage) == -1) {
         | 
| 88 87 | 
             
            			int e = errno;
         | 
| @@ -122,7 +121,7 @@ public: | |
| 122 121 | 
             
            		}
         | 
| 123 122 | 
             
            		pos = appendData(pos, end, id);
         | 
| 124 123 | 
             
            		pos = appendData(pos, end, " (");
         | 
| 125 | 
            -
            		pos = appendData(pos, end, usecToString( | 
| 124 | 
            +
            		pos = appendData(pos, end, usecToString(SystemTime::getMonotonicUsec()));
         | 
| 126 125 | 
             
            		pos = appendData(pos, end, ",");
         | 
| 127 126 | 
             
            		if (getrusage(RUSAGE_SELF, &usage) == -1) {
         | 
| 128 127 | 
             
            			int e = errno;
         | 
    
        data/src/agent/Shared/Base.cpp
    CHANGED
    
    | @@ -64,6 +64,7 @@ | |
| 64 64 | 
             
            #include <Logging.h>
         | 
| 65 65 | 
             
            #include <ResourceLocator.h>
         | 
| 66 66 | 
             
            #include <Utils.h>
         | 
| 67 | 
            +
            #include <Utils/SystemTime.h>
         | 
| 67 68 | 
             
            #include <Utils/StrIntUtils.h>
         | 
| 68 69 | 
             
            #ifdef __linux__
         | 
| 69 70 | 
             
            	#include <ResourceLocator.h>
         | 
| @@ -1500,6 +1501,7 @@ initializeAgent(int argc, char **argv[], const char *processName, | |
| 1500 1501 | 
             
            	if (hasEnvOption("PASSENGER_SIMULATE_SYSCALL_FAILURES")) {
         | 
| 1501 1502 | 
             
            		initializeSyscallFailureSimulation(processName);
         | 
| 1502 1503 | 
             
            	}
         | 
| 1504 | 
            +
            	SystemTime::initialize();
         | 
| 1503 1505 | 
             
            	setvbuf(stdout, NULL, _IONBF, 0);
         | 
| 1504 1506 | 
             
            	setvbuf(stderr, NULL, _IONBF, 0);
         | 
| 1505 1507 |  | 
| @@ -1645,4 +1647,34 @@ shutdownAgent(VariantMap *agentOptions) { | |
| 1645 1647 | 
             
            	oxt::shutdown();
         | 
| 1646 1648 | 
             
            }
         | 
| 1647 1649 |  | 
| 1650 | 
            +
            void
         | 
| 1651 | 
            +
            restoreOomScore(VariantMap *agentOptions) {
         | 
| 1652 | 
            +
            	TRACE_POINT();
         | 
| 1653 | 
            +
             | 
| 1654 | 
            +
            	string score = agentOptions->get("original_oom_score", false);
         | 
| 1655 | 
            +
            	if (score.empty()) {
         | 
| 1656 | 
            +
            		return;
         | 
| 1657 | 
            +
            	}
         | 
| 1658 | 
            +
             | 
| 1659 | 
            +
            	FILE *f;
         | 
| 1660 | 
            +
            	bool legacy = false;
         | 
| 1661 | 
            +
             | 
| 1662 | 
            +
            	if (score.at(0) == 'l') {
         | 
| 1663 | 
            +
            		legacy = true;
         | 
| 1664 | 
            +
            		score = score.substr(1);
         | 
| 1665 | 
            +
            		f = fopen("/proc/self/oom_adj", "w");
         | 
| 1666 | 
            +
            	} else {
         | 
| 1667 | 
            +
            		f = fopen("/proc/self/oom_score_adj", "w");
         | 
| 1668 | 
            +
            	}
         | 
| 1669 | 
            +
             | 
| 1670 | 
            +
            	if (f != NULL) {
         | 
| 1671 | 
            +
            		fprintf(f, "%s\n", score.c_str());
         | 
| 1672 | 
            +
            		fclose(f);
         | 
| 1673 | 
            +
            	} else {
         | 
| 1674 | 
            +
            		P_WARN("Unable to set OOM score to " << score << " (legacy: " << legacy
         | 
| 1675 | 
            +
            				<< ") due to error: " << strerror(errno)
         | 
| 1676 | 
            +
            				<< " (process will remain at inherited OOM score)");
         | 
| 1677 | 
            +
            	}
         | 
| 1678 | 
            +
            }
         | 
| 1679 | 
            +
             | 
| 1648 1680 | 
             
            } // namespace Passenger
         | 
    
        data/src/agent/Shared/Base.h
    CHANGED
    
    
| @@ -203,7 +203,7 @@ protected: | |
| 203 203 | 
             
            	 * <em>timeout</em> miliseconds for the process to exit.
         | 
| 204 204 | 
             
            	 */
         | 
| 205 205 | 
             
            	static int timedWaitPid(pid_t pid, int *status, unsigned long long timeout) {
         | 
| 206 | 
            -
            		Timer timer;
         | 
| 206 | 
            +
            		Timer<SystemTime::GRAN_10MSEC> timer;
         | 
| 207 207 | 
             
            		int ret;
         | 
| 208 208 |  | 
| 209 209 | 
             
            		do {
         | 
| @@ -308,8 +308,6 @@ public: | |
| 308 308 | 
             
            			 * only affects the watchdog but not agents. */
         | 
| 309 309 | 
             
            			setpgid(getpid(), getpid());
         | 
| 310 310 |  | 
| 311 | 
            -
            			setOomScore(oldOomScore);
         | 
| 312 | 
            -
             | 
| 313 311 | 
             
            			try {
         | 
| 314 312 | 
             
            				execProgram();
         | 
| 315 313 | 
             
            			} catch (...) {
         | 
| @@ -162,7 +162,7 @@ static void cleanup(const WorkingObjectsPtr &wo); | |
| 162 162 | 
             
            /***** Functions *****/
         | 
| 163 163 |  | 
| 164 164 | 
             
            static FILE *
         | 
| 165 | 
            -
             | 
| 165 | 
            +
            openOomAdjFileGetType(const char *mode, OomFileType &type) {
         | 
| 166 166 | 
             
            	FILE *f = fopen("/proc/self/oom_score_adj", mode);
         | 
| 167 167 | 
             
            	if (f == NULL) {
         | 
| 168 168 | 
             
            		f = fopen("/proc/self/oom_adj", mode);
         | 
| @@ -178,6 +178,16 @@ openOomAdjFile(const char *mode, OomFileType &type) { | |
| 178 178 | 
             
            	}
         | 
| 179 179 | 
             
            }
         | 
| 180 180 |  | 
| 181 | 
            +
            static FILE *
         | 
| 182 | 
            +
            openOomAdjFileForcedType(const char *mode, OomFileType &type) {
         | 
| 183 | 
            +
            	if (type == OOM_SCORE_ADJ) {
         | 
| 184 | 
            +
            		return fopen("/proc/self/oom_score_adj", mode);
         | 
| 185 | 
            +
            	} else {
         | 
| 186 | 
            +
            		assert(type == OOM_ADJ);
         | 
| 187 | 
            +
            		return fopen("/proc/self/oom_adj", mode);
         | 
| 188 | 
            +
            	}
         | 
| 189 | 
            +
            }
         | 
| 190 | 
            +
             | 
| 181 191 | 
             
            /**
         | 
| 182 192 | 
             
             * Linux-only way to change OOM killer configuration for
         | 
| 183 193 | 
             
             * current process. Requires root privileges, which we
         | 
| @@ -191,14 +201,24 @@ setOomScore(const StaticString &score) { | |
| 191 201 |  | 
| 192 202 | 
             
            	FILE *f;
         | 
| 193 203 | 
             
            	OomFileType type;
         | 
| 204 | 
            +
            	string filteredScore;
         | 
| 194 205 |  | 
| 195 | 
            -
            	 | 
| 206 | 
            +
            	if (score.at(0) == 'l') {
         | 
| 207 | 
            +
            		filteredScore = score.substr(1);
         | 
| 208 | 
            +
            		type = OOM_ADJ;
         | 
| 209 | 
            +
            	} else {
         | 
| 210 | 
            +
            		filteredScore = score;
         | 
| 211 | 
            +
            		type = OOM_SCORE_ADJ;
         | 
| 212 | 
            +
            	}
         | 
| 213 | 
            +
            	f = openOomAdjFileForcedType("w", type);
         | 
| 196 214 | 
             
            	if (f != NULL) {
         | 
| 197 | 
            -
            		size_t ret = fwrite( | 
| 215 | 
            +
            		size_t ret = fwrite(filteredScore.data(), 1, filteredScore.size(), f);
         | 
| 198 216 | 
             
            		// We can't do anything about failures, so ignore compiler
         | 
| 199 217 | 
             
            		// warnings about not doing anything with the result.
         | 
| 200 218 | 
             
            		(void) ret;
         | 
| 201 219 | 
             
            		fclose(f);
         | 
| 220 | 
            +
            	} else {
         | 
| 221 | 
            +
            		P_WARN("setOomScore(" << filteredScore << ", " << type << ") failed due to error: " << strerror(errno));
         | 
| 202 222 | 
             
            	}
         | 
| 203 223 | 
             
            }
         | 
| 204 224 |  | 
| @@ -211,10 +231,14 @@ setOomScoreNeverKill() { | |
| 211 231 | 
             
            	FILE *f;
         | 
| 212 232 | 
             
            	OomFileType type;
         | 
| 213 233 |  | 
| 214 | 
            -
            	f =  | 
| 234 | 
            +
            	f = openOomAdjFileGetType("r", type);
         | 
| 215 235 | 
             
            	if (f == NULL) {
         | 
| 216 236 | 
             
            		return "";
         | 
| 217 237 | 
             
            	}
         | 
| 238 | 
            +
            	// mark if this is a legacy score so we won't try to write it as OOM_SCORE_ADJ
         | 
| 239 | 
            +
            	if (type == OOM_ADJ) {
         | 
| 240 | 
            +
            		oldScore.append("l");
         | 
| 241 | 
            +
            	}
         | 
| 218 242 | 
             
            	char buf[1024];
         | 
| 219 243 | 
             
            	size_t bytesRead;
         | 
| 220 244 | 
             
            	while (true) {
         | 
| @@ -230,7 +254,7 @@ setOomScoreNeverKill() { | |
| 230 254 | 
             
            	}
         | 
| 231 255 | 
             
            	fclose(f);
         | 
| 232 256 |  | 
| 233 | 
            -
            	f =  | 
| 257 | 
            +
            	f = openOomAdjFileForcedType("w", type);
         | 
| 234 258 | 
             
            	if (f == NULL) {
         | 
| 235 259 | 
             
            		return "";
         | 
| 236 260 | 
             
            	}
         | 
| @@ -397,7 +421,7 @@ cleanupAgentsInBackground(const WorkingObjectsPtr &wo, vector<AgentWatcherPtr> & | |
| 397 421 | 
             
            		// Child
         | 
| 398 422 | 
             
            		try {
         | 
| 399 423 | 
             
            			vector<AgentWatcherPtr>::const_iterator it;
         | 
| 400 | 
            -
            			Timer timer(false);
         | 
| 424 | 
            +
            			Timer<SystemTime::GRAN_10MSEC> timer(false);
         | 
| 401 425 | 
             
            			fd_set fds, fds2;
         | 
| 402 426 | 
             
            			int max, agentProcessesDone;
         | 
| 403 427 | 
             
            			unsigned long long deadline = 30000; // miliseconds
         | 
| @@ -781,6 +805,7 @@ initializeBareEssentials(int argc, char *argv[], WorkingObjectsPtr &wo) { | |
| 781 805 | 
             
            	agentsOptions = new VariantMap();
         | 
| 782 806 | 
             
            	*agentsOptions = initializeAgent(argc, &argv, SHORT_PROGRAM_NAME " watchdog",
         | 
| 783 807 | 
             
            		parseOptions, NULL, 2);
         | 
| 808 | 
            +
            	agentsOptions->set("original_oom_score", oldOomScore);
         | 
| 784 809 |  | 
| 785 810 | 
             
            	// Start all sub-agents with this environment variable.
         | 
| 786 811 | 
             
            	setenv("PASSENGER_USE_FEEDBACK_FD", "true", 1);
         |