From 852ec545193a42a096391dbb4d311ae4962f480c Mon Sep 17 00:00:00 2001 From: Weibing Wang Date: Wed, 26 Jul 2017 17:29:15 +0800 Subject: [PATCH] implement fastcgi_finish_request() Change-Id: I6a8322e7030060c619397cd39a94c660c1f214ce --- hphp/runtime/ext/phpfpm/config.cmake | 9 +++ hphp/runtime/ext/phpfpm/ext_phpfpm.cpp | 60 +++++++++++++++++++ hphp/runtime/ext/phpfpm/ext_phpfpm.h | 32 ++++++++++ hphp/runtime/ext/phpfpm/ext_phpfpm.php | 10 ++++ .../server/fastcgi/fastcgi-transport.cpp | 3 + .../server/proxygen/proxygen-transport.cpp | 2 +- .../test_fastcgi_finish_request.php | 14 +++++ .../fastcgi/tests/fastcgi_finish_request.php | 8 +++ .../tests/fastcgi_finish_request.php.expect | 4 ++ hphp/util/hphp-config.h.in | 3 +- 10 files changed, 143 insertions(+), 2 deletions(-) create mode 100644 hphp/runtime/ext/phpfpm/config.cmake create mode 100755 hphp/runtime/ext/phpfpm/ext_phpfpm.cpp create mode 100644 hphp/runtime/ext/phpfpm/ext_phpfpm.h create mode 100644 hphp/runtime/ext/phpfpm/ext_phpfpm.php create mode 100644 hphp/test/server/fastcgi/server_root/test_fastcgi_finish_request.php create mode 100644 hphp/test/server/fastcgi/tests/fastcgi_finish_request.php create mode 100644 hphp/test/server/fastcgi/tests/fastcgi_finish_request.php.expect diff --git a/hphp/runtime/ext/phpfpm/config.cmake b/hphp/runtime/ext/phpfpm/config.cmake new file mode 100644 index 00000000000000..977cdf2c9f339d --- /dev/null +++ b/hphp/runtime/ext/phpfpm/config.cmake @@ -0,0 +1,9 @@ +HHVM_DEFINE_EXTENSION("phpfpm" + SOURCES + ext_phpfpm.cpp + HEADERS + ext_phpfpm.h + SYSTEMLIB + ext_phpfpm.php + DEPENDS +) diff --git a/hphp/runtime/ext/phpfpm/ext_phpfpm.cpp b/hphp/runtime/ext/phpfpm/ext_phpfpm.cpp new file mode 100755 index 00000000000000..317c6729843543 --- /dev/null +++ b/hphp/runtime/ext/phpfpm/ext_phpfpm.cpp @@ -0,0 +1,60 @@ +/* + +----------------------------------------------------------------------+ + | HipHop for PHP | + +----------------------------------------------------------------------+ + | Copyright (c) 2010-present Facebook, Inc. (http://www.facebook.com) | + | Copyright (c) 1997-2010 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ +*/ + +#include "hphp/runtime/ext/phpfpm/ext_phpfpm.h" +#include "hphp/runtime/base/execution-context.h" + +namespace HPHP { + +bool HHVM_FUNCTION(fastcgi_finish_request) { + auto context = g_context.getNoCheck(); + auto transport = context->getTransport(); + if (!transport) { + return false; + } + context->obFlushAll(); + String content = context->obDetachContents(); + + // User may use fastcgi_finish_request in shutdown functions + // Shutdown functions will be invoked even if fatal error occurs + int errnum = g_context->getLastErrorNumber(); + if (errnum == static_cast(ErrorMode::FATAL_ERROR)){ + if (RuntimeOption::ServerErrorMessage) { + String lastError = g_context->getLastError(); + transport->sendString(lastError.data(), + 500, false, false, "hphp_invoke"); + } else { + transport->sendString(RuntimeOption::FatalErrorMessage, + 500, false, false, "hphp_invoke"); + } + } else { + transport->sendRaw((void*)content.data(), content.size()); + } + transport->onSendEnd(); + return true; +} + +class PHPFpmExtension : public Extension { + public: + PHPFpmExtension() : Extension("cgi-fcgi", "1.0.0") {} + void moduleInit() override { + HHVM_FE(fastcgi_finish_request); + loadSystemlib("phpfpm"); + } +} s_phpfpm_extension; + +} diff --git a/hphp/runtime/ext/phpfpm/ext_phpfpm.h b/hphp/runtime/ext/phpfpm/ext_phpfpm.h new file mode 100644 index 00000000000000..6af0feb39500e1 --- /dev/null +++ b/hphp/runtime/ext/phpfpm/ext_phpfpm.h @@ -0,0 +1,32 @@ +/* + +----------------------------------------------------------------------+ + | HipHop for PHP | + +----------------------------------------------------------------------+ + | Copyright (c) 2010-present Facebook, Inc. (http://www.facebook.com) | + | Copyright (c) 1997-2010 The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | http://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ +*/ + +#ifndef incl_HPHP_EXT_PHPFPM_H +#define incl_HPHP_EXT_PHPFPM_H + +#include "hphp/runtime/ext/extension.h" + +namespace HPHP { +/////////////////////////////////////////////////////////////////////////////// + +bool HHVM_FUNCTION(fastcgi_finish_request); + +/////////////////////////////////////////////////////////////////////////////// +} + +#endif // incl_HPHP_EXT_PHPFPM_H + diff --git a/hphp/runtime/ext/phpfpm/ext_phpfpm.php b/hphp/runtime/ext/phpfpm/ext_phpfpm.php new file mode 100644 index 00000000000000..b1ca1a7e6179fb --- /dev/null +++ b/hphp/runtime/ext/phpfpm/ext_phpfpm.php @@ -0,0 +1,10 @@ +> +function fastcgi_finish_request(): bool; + diff --git a/hphp/runtime/server/fastcgi/fastcgi-transport.cpp b/hphp/runtime/server/fastcgi/fastcgi-transport.cpp index 594e2020666a4b..38bd7776e48ee8 100644 --- a/hphp/runtime/server/fastcgi/fastcgi-transport.cpp +++ b/hphp/runtime/server/fastcgi/fastcgi-transport.cpp @@ -167,6 +167,9 @@ void FastCGITransport::sendResponseHeaders(IOBufQueue& queue, int code) { void FastCGITransport::sendImpl(const void* data, int size, int code, bool /*chunked*/, bool eom) { + if (m_sendEnded) { + return; // Output after fastcgi_finish_request will be ignored + } if (!m_headersSent) { m_headersSent = true; sendResponseHeaders(m_txBuf, code); diff --git a/hphp/runtime/server/proxygen/proxygen-transport.cpp b/hphp/runtime/server/proxygen/proxygen-transport.cpp index 049706b589d61b..c9adddfd7ef334 100644 --- a/hphp/runtime/server/proxygen/proxygen-transport.cpp +++ b/hphp/runtime/server/proxygen/proxygen-transport.cpp @@ -661,7 +661,6 @@ void ProxygenTransport::messageAvailable(ResponseMessage&& message) noexcept { void ProxygenTransport::sendImpl(const void *data, int size, int code, bool chunked, bool eom) { assert(data); - assert(!m_sendStarted || chunked); if (m_sendEnded) { // This should never happen, but when it does we have to bail out, // since there's no sensible way to send data at this point and @@ -670,6 +669,7 @@ void ProxygenTransport::sendImpl(const void *data, int size, int code, // somewhere. return; } + assert(!m_sendStarted || chunked); VLOG(4) << "sendImpl called with data size=" << size << ", code=" << code << ", chunked=" << chunked << ", eom=" << eom; diff --git a/hphp/test/server/fastcgi/server_root/test_fastcgi_finish_request.php b/hphp/test/server/fastcgi/server_root/test_fastcgi_finish_request.php new file mode 100644 index 00000000000000..0641d914920a1e --- /dev/null +++ b/hphp/test/server/fastcgi/server_root/test_fastcgi_finish_request.php @@ -0,0 +1,14 @@ +