Created
July 18, 2020 02:57
-
-
Save jjergus/ff131a33772486d2b011faf56baf33c6 to your computer and use it in GitHub Desktop.
PoC fix for asyncpoll blocked forever after close
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/hphp/runtime/base/file-await.cpp b/hphp/runtime/base/file-await.cpp | |
index 6414eac085..78a3cdb366 100644 | |
--- a/hphp/runtime/base/file-await.cpp | |
+++ b/hphp/runtime/base/file-await.cpp | |
@@ -21,6 +21,12 @@ void FileEventHandler::handlerReady(uint16_t events) noexcept { | |
///////////////////////////////////////////////////////////////////////////// | |
+void FileAwait::jj_cancel() { | |
+ if (m_file) { | |
+ m_file->unregisterHandler(); | |
+ } | |
+} | |
+ | |
FileAwait::FileAwait( | |
int fd, | |
uint16_t events, | |
diff --git a/hphp/runtime/base/file-await.h b/hphp/runtime/base/file-await.h | |
index 972ea43a53..a543904f6a 100644 | |
--- a/hphp/runtime/base/file-await.h | |
+++ b/hphp/runtime/base/file-await.h | |
@@ -46,6 +46,8 @@ struct FileAwait : AsioExternalThreadEvent { | |
CLOSED, | |
}; | |
+ void jj_cancel(); | |
+ | |
FileAwait(int fd, uint16_t events, std::chrono::nanoseconds timeout); | |
~FileAwait(); | |
void unserialize(TypedValue& c) override; | |
diff --git a/hphp/runtime/ext/asio/ext_external-thread-event-wait-handle.h b/hphp/runtime/ext/asio/ext_external-thread-event-wait-handle.h | |
index 9c62636952..d6b24595c9 100644 | |
--- a/hphp/runtime/ext/asio/ext_external-thread-event-wait-handle.h | |
+++ b/hphp/runtime/ext/asio/ext_external-thread-event-wait-handle.h | |
@@ -55,6 +55,10 @@ struct c_ExternalThreadEventWaitHandle final : c_WaitableWaitHandle { | |
} | |
ObjectData* getPrivData() { return m_privData.get(); } | |
+ // Yes I know, there's probably a good reason why this wasn't here, but this | |
+ // is just a PoC so bear with me. | |
+ AsioExternalThreadEvent* getEvent() { return m_event; } | |
+ | |
void abandon(bool sweeping); | |
bool cancel(const Object& exception); | |
void process(); | |
diff --git a/hphp/runtime/ext/hsl/ext_hsl_os.cpp b/hphp/runtime/ext/hsl/ext_hsl_os.cpp | |
index 9a20a4f1a2..af4842ffa7 100644 | |
--- a/hphp/runtime/ext/hsl/ext_hsl_os.cpp | |
+++ b/hphp/runtime/ext/hsl/ext_hsl_os.cpp | |
@@ -586,6 +586,18 @@ void HHVM_FUNCTION(HSL_os_close, const Object& obj) { | |
HSLFileDescriptor::get(obj)->close(); | |
} | |
+void HHVM_FUNCTION(HSL_os_cancel_async_poll, const Object& obj) { | |
+ if (!obj->instanceof(c_ExternalThreadEventWaitHandle::classof())) { | |
+ SystemLib::throwInvalidArgumentExceptionObject( | |
+ "Argument must be ExternalThreadEventWaitHandle"); | |
+ } | |
+ c_ExternalThreadEventWaitHandle* handle = | |
+ wait_handle<c_ExternalThreadEventWaitHandle>(obj.get()); | |
+ AsioExternalThreadEvent* event = handle->getEvent(); | |
+ FileAwait* file_await = static_cast<FileAwait*>(event); | |
+ file_await->jj_cancel(); | |
+} | |
+ | |
Array HHVM_FUNCTION(HSL_os_pipe) { | |
int fds[2]; | |
throw_errno_if_minus_one(retry_on_eintr(-1, ::pipe, fds)); | |
@@ -1202,6 +1214,7 @@ struct OSExtension final : Extension { | |
HHVM_FALIAS(HH\\Lib\\_Private\\_OS\\read, HSL_os_read); | |
HHVM_FALIAS(HH\\Lib\\_Private\\_OS\\write, HSL_os_write); | |
HHVM_FALIAS(HH\\Lib\\_Private\\_OS\\close, HSL_os_close); | |
+ HHVM_FALIAS(HH\\Lib\\_Private\\_OS\\cancel_async_poll, HSL_os_cancel_async_poll); | |
HHVM_FALIAS(HH\\Lib\\_Private\\_OS\\request_stdio_fd, HSL_os_request_stdio_fd); | |
HHVM_RC_INT(HH\\Lib\\_Private\\_OS\\STDIN_FILENO, STDIN_FILENO); | |
diff --git a/hphp/runtime/ext/hsl/ext_hsl_os.php b/hphp/runtime/ext/hsl/ext_hsl_os.php | |
index 506465508e..01978f80f1 100644 | |
--- a/hphp/runtime/ext/hsl/ext_hsl_os.php | |
+++ b/hphp/runtime/ext/hsl/ext_hsl_os.php | |
@@ -55,6 +55,9 @@ function write(FileDescriptor $fd, string $data): int; | |
<<__Native>> | |
function close(FileDescriptor $fd): void; | |
+<<__Native>> | |
+function cancel_async_poll(WaitHandle $wait_handle): void; | |
+ | |
<<__Native>> | |
function pipe(): varray<FileDescriptor>; | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/src/network/_Private/CancelablePoller.php b/src/network/_Private/CancelablePoller.php | |
index 9cc13c8..5cb382a 100644 | |
--- a/src/network/_Private/CancelablePoller.php | |
+++ b/src/network/_Private/CancelablePoller.php | |
@@ -39,6 +39,7 @@ final class CancelablePoller { | |
public function cancelAll(int $result): void { | |
$ex = new PollCancelledException($result); | |
foreach ($this->polls as $poll) { | |
+ _OS\cancel_async_poll($poll); | |
\HH\Asio\cancel($poll, $ex); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment