Exemplo n.º 1
0
	void initChild(apr_pool_t *pchild, server_rec *s) {
		ServerConfig *config = getServerConfig(s);
		
		try {
			applicationPool = applicationPoolServer->connect();
			applicationPoolServer->detach();
			applicationPool->setMax(config->maxPoolSize);
			applicationPool->setMaxPerApp(config->maxInstancesPerApp);
			applicationPool->setMaxIdleTime(config->poolIdleTime);
		} catch (const thread_interrupted &) {
			P_TRACE(3, "A system call was interrupted during initialization of "
				"an Apache child process. Apache is probably restarting or "
				"shutting down.");
		} catch (const exception &e) {
			P_WARN("Cannot initialize Passenger in an Apache child process: " <<
				e.what() <<
				" (this warning is harmless if you're currently restarting "
				"or shutting down Apache)\n");
			abort();
		}
	}
Exemplo n.º 2
0
	int handleRequest(request_rec *r) {
		DirConfig *config = getDirConfig(r);
		DirectoryMapper mapper(r, config);
		if (mapper.getBaseURI() == NULL || r->filename == NULL || fileExists(r->filename)) {
			return DECLINED;
		}
		
		try {
			if (mapper.getPublicDirectory().empty()) {
				return reportDocumentRootDeterminationError(r);
			}
		} catch (const FileSystemException &e) {
			return reportFileSystemError(r, e);
		}
		
		int httpStatus = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR);
    		if (httpStatus != OK) {
			return httpStatus;
		}
		
		try {
			this_thread::disable_interruption di;
			this_thread::disable_syscall_interruption dsi;
			apr_bucket_brigade *bb;
			apr_bucket *b;
			Application::SessionPtr session;
			bool expectingUploadData;
			shared_ptr<TempFile> uploadData;
			
			expectingUploadData = ap_should_client_block(r);
			if (expectingUploadData && atol(lookupHeader(r, "Content-Length"))
			                                 > UPLOAD_ACCELERATION_THRESHOLD) {
				uploadData = receiveRequestBody(r);
			}
			
			try {
				const char *defaultUser, *environment, *spawnMethod;
				unsigned int appSpawnerTimeout, frameworkSpawnerTimeout;
				ServerConfig *sconfig;
				
				sconfig = getServerConfig(r->server);
				if (sconfig->defaultUser != NULL) {
					defaultUser = sconfig->defaultUser;
				} else {
					defaultUser = "******";
				}
				if (mapper.getApplicationType() == DirectoryMapper::RAILS) {
					if (config->railsEnv == NULL) {
						environment = DEFAULT_RAILS_ENV;
					} else {
						environment = config->railsEnv;
					}
				} else if (mapper.getApplicationType() == DirectoryMapper::RACK) {
					if (config->rackEnv == NULL) {
						environment = DEFAULT_RACK_ENV;
					} else {
						environment = config->rackEnv;
					}
				} else {
					environment = DEFAULT_WSGI_ENV;
				}
				if (config->spawnMethod == DirConfig::SM_CONSERVATIVE) {
					spawnMethod = "conservative";
				} else {
					spawnMethod = "smart";
				}
				if (config->frameworkSpawnerTimeout < 0) {
					frameworkSpawnerTimeout = 0;
				} else {
					frameworkSpawnerTimeout = config->frameworkSpawnerTimeout;
				}
				if (config->appSpawnerTimeout < 0) {
					appSpawnerTimeout = 0;
				} else {
					appSpawnerTimeout = config->appSpawnerTimeout;
				}
				
				session = applicationPool->get(SpawnOptions(
					canonicalizePath(mapper.getPublicDirectory() + "/.."),
					true, defaultUser, environment, spawnMethod,
					mapper.getApplicationTypeString(),
					appSpawnerTimeout, frameworkSpawnerTimeout));
				P_TRACE(3, "Forwarding " << r->uri << " to PID " << session->getPid());
			} catch (const SpawnException &e) {
				if (e.hasErrorPage()) {
					ap_set_content_type(r, "text/html; charset=utf-8");
					ap_rputs(e.getErrorPage().c_str(), r);
					// Unfortunately we can't return a 500 Internal Server
					// Error. Apache's HTTP error handler would kick in.
					return OK;
				} else {
					throw;
				}
			} catch (const BusyException &e) {
				return reportBusyException(r);
			}
			
			session->setReaderTimeout(r->server->timeout / 1000);
			session->setWriterTimeout(r->server->timeout / 1000);
			sendHeaders(r, session, mapper.getBaseURI());
			if (expectingUploadData) {
				if (uploadData != NULL) {
					sendRequestBody(r, session, uploadData);
					uploadData.reset();
				} else {
					sendRequestBody(r, session);
				}
			}
			session->shutdownWriter();
			
			apr_file_t *readerPipe = NULL;
			int reader = session->getStream();
			apr_os_pipe_put(&readerPipe, &reader, r->pool);
			apr_file_pipe_timeout_set(readerPipe, r->server->timeout);

			bb = apr_brigade_create(r->connection->pool, r->connection->bucket_alloc);
			b = apr_bucket_pipe_create(readerPipe, r->connection->bucket_alloc);
			APR_BRIGADE_INSERT_TAIL(bb, b);

			b = apr_bucket_eos_create(r->connection->bucket_alloc);
			APR_BRIGADE_INSERT_TAIL(bb, b);

			ap_scan_script_header_err_brigade(r, bb, NULL);
			ap_pass_brigade(r->output_filters, bb);
			
			Container *container = new Container();
			container->session = session;
			apr_pool_cleanup_register(r->pool, container, Container::cleanup, apr_pool_cleanup_null);
			
			// Apparently apr_bucket_pipe or apr_brigade closes the
			// file descriptor for us.
			session->discardStream();

			return OK;
			
		} catch (const thread_interrupted &e) {
			P_TRACE(3, "A system call was interrupted during an HTTP request. Apache "
				"is probably restarting or shutting down. Backtrace:\n" <<
				e.backtrace());
			return HTTP_INTERNAL_SERVER_ERROR;
			
		} catch (const tracable_exception &e) {
			P_TRACE(3, "Unexpected error in mod_passenger: " <<
				e.what() << "\n" << "  Backtrace:" << e.backtrace());
			return HTTP_INTERNAL_SERVER_ERROR;
		
		} catch (const exception &e) {
			P_TRACE(3, "Unexpected error in mod_passenger: " <<
				e.what() << "\n" << "  Backtrace: not available");
			return HTTP_INTERNAL_SERVER_ERROR;
		
		} catch (...) {
			P_TRACE(3, "An unexpected, unknown error occured in mod_passenger.");
			throw;
		}
	}
Exemplo n.º 3
0
	static Application::SessionPtr spawnWsgiApp(ApplicationPoolPtr pool, const char *appRoot) {
		PoolOptions options;
		options.appRoot = appRoot;
		options.appType = "wsgi";
		return pool->get(options);
	}
Exemplo n.º 4
0
	static Application::SessionPtr spawnRackApp(ApplicationPoolPtr pool, const char *appRoot) {
		SpawnOptions options;
		options.appRoot = appRoot;
		options.appType = "rack";
		return pool->get(options);
	}