This is an automated email from the ASF dual-hosted git repository.

bmahler pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mesos.git

commit a7d5b9355e03d64268d5b6f760dd2af6fe7e923b
Author: Benjamin Mahler <[email protected]>
AuthorDate: Fri May 3 15:53:28 2019 -0400

    Adds a regression test for MESOS-9766.
    
    This test fails on master prior to applying the fix for MESOS-9766.
    It attempts to ensure that processes are terminated after the
    /__processes__ handler dispatches to them.
    
    Review: https://reviews.apache.org/r/70595
---
 3rdparty/libprocess/src/tests/process_tests.cpp | 66 +++++++++++++++++++++++++
 1 file changed, 66 insertions(+)

diff --git a/3rdparty/libprocess/src/tests/process_tests.cpp 
b/3rdparty/libprocess/src/tests/process_tests.cpp
index 60f3dd6..05dc5ec 100644
--- a/3rdparty/libprocess/src/tests/process_tests.cpp
+++ b/3rdparty/libprocess/src/tests/process_tests.cpp
@@ -78,7 +78,10 @@ using process::defer;
 using process::Deferred;
 using process::Event;
 using process::Executor;
+using process::DispatchEvent;
 using process::ExitedEvent;
+using process::TerminateEvent;
+using process::Failure;
 using process::Future;
 using process::Message;
 using process::MessageEncoder;
@@ -87,6 +90,7 @@ using process::Owned;
 using process::PID;
 using process::Process;
 using process::ProcessBase;
+using process::Promise;
 using process::run;
 using process::Subprocess;
 using process::TerminateEvent;
@@ -2081,3 +2085,65 @@ TEST_F(ProcessTest, FirewallUninstall)
   terminate(process);
   wait(process);
 }
+
+
+// This ensures that the `/__processes__` endpoint does not hang
+// if one of the dispatches is abandoned. This can occur if a
+// process is terminated with `inject == true` after the
+// `/__processes__` endpoint handler has dispatched to it.
+TEST_F(ProcessTest, ProcessesEndpointNoHang)
+{
+  // This process will hold itself in a dispatch handler
+  // until both are present in its event queue:
+  //   (1) an injected terminate event, and
+  //   (2) a dispatch event from the `__processes__` endpoint.
+  //
+  // At that point, we know that the future for (2) will get
+  // abandoned.
+  class TestProcess : public Process<TestProcess>
+  {
+  public:
+    Future<Nothing> wait_for_terminate(Promise<Nothing>&& p)
+    {
+      p.set(Nothing()); // Notify that we're inside the function.
+
+      Time start = Clock::now();
+
+      while (Clock::now() - start < process::TEST_AWAIT_TIMEOUT) {
+        if (eventCount<TerminateEvent>() == 1 &&
+            eventCount<DispatchEvent>() == 1) {
+          return Nothing();
+        }
+
+        os::sleep(Milliseconds(1));
+      }
+
+      return Failure("Timed out waiting for terminate and dispatch");
+    }
+  };
+
+  PID<TestProcess> process = spawn(new TestProcess(), true);
+
+  Promise<Nothing> promise;
+  Future<Nothing> inside = promise.future();
+
+  Future<Nothing> waited =
+    dispatch(process, &TestProcess::wait_for_terminate, std::move(promise));
+
+  AWAIT_READY(inside);
+
+  http::URL url = http::URL(
+      "http",
+      process::address().ip,
+      process::address().port,
+      "/__processes__");
+
+  Future<http::Response> response = http::get(url);
+
+  terminate(process, true);
+
+  AWAIT_READY(waited);
+
+  AWAIT_READY(response);
+  EXPECT_EQ(http::Status::OK, response->code);
+}

Reply via email to