Fixed a bug where timers wouldn't expire after `process:reinitialize`.

Pending `ticks` are used by `scheduleTick` to decide whether to schedule
an event loop tick when a new timer is scheduled - since we only need to
schedule the event loop tick if the new timer is supposed to expire
earlier than the current earliest timer.
Unfortunately `Clock::finalize` didn't clear `ticks`, which means that
the following could happen:
- schedule a timer T0 for expiration at time t0
- call `process::reinitalize`, which calls `Clock::finalize` but doesn't
  clear `ticks`
- schedule a new timer T1 for expiration at time t1 > t0: since
  `scheduleTick` would see that there was already the earlier pending
  tick for T0 in `ticks` with t0 < t1, it wouldn't actually schedule a
  tick of the event loop

Therefore new timers would never fire again.

This caused e.g.
`DockerContainerizerIPv6Test.ROOT_DOCKER_LaunchIPv6HostNetwork` test to
hang since it called `process::reinitialized` while having some active
timers - e.g. the reaper periodic timer.

Also added a test specifically for this bug.
diff --git a/3rdparty/libprocess/src/clock.cpp b/3rdparty/libprocess/src/clock.cpp
index 519c69e..7307de9 100644
--- a/3rdparty/libprocess/src/clock.cpp
+++ b/3rdparty/libprocess/src/clock.cpp
@@ -218,11 +218,13 @@
   synchronized (timers_mutex) {
     // NOTE: `currents` is only non-empty when the clock is paused.
 
-    // This, along with the `timers_mutex`, is all that is required to clean
-    // up any pending timers.  Timers are triggered via "ticks".  However,
-    // we do not need to clear `ticks` because a "tick" with an empty `timers`
-    // map will effectively be a no-op.
+    // Clear both timers and ticks.
+    // Note that we need to clear `ticks` as well because the earliest tick in
+    // `ticks` is used by `scheduleTick` to decide whether to schedule an event
+    // loop tick when a new timer is added, so not clearing `ticks` could
+    // cause, after reinitialization, new timers to never fire.
     timers->clear();
+    clock::ticks->clear();
   }
 }
 
diff --git a/3rdparty/libprocess/src/tests/process_tests.cpp b/3rdparty/libprocess/src/tests/process_tests.cpp
index eabd70e..d47c19b 100644
--- a/3rdparty/libprocess/src/tests/process_tests.cpp
+++ b/3rdparty/libprocess/src/tests/process_tests.cpp
@@ -114,6 +114,17 @@
 using testing::Return;
 using testing::ReturnArg;
 
+
+namespace process {
+
+// Used by TimerAfterReinitialize.
+void reinitialize(
+    const Option<string>& delegate,
+    const Option<string>& readonlyAuthenticationRealm,
+    const Option<string>& readwriteAuthenticationRealm);
+
+}
+
 // TODO(bmahler): Move tests into their own files as appropriate.
 
 class ProcessTest : public TemporaryDirectoryTest {};
@@ -2109,3 +2120,29 @@
   AWAIT_READY(response);
   EXPECT_EQ(http::Status::OK, response->code);
 }
+
+
+// Test for a bug where timers wouldn't be handled after libprocess was
+// reinitialized.
+TEST_F(ProcessTest, TimerAfterReinitialize)
+{
+  // Schedule a timer, which won't have time to expire before...
+  process::Timer timer_before = Clock::timer(Milliseconds(10), []() {});
+
+  // We reinitialize libprocess.
+  process::reinitialize(
+    None(),
+    process::READWRITE_HTTP_AUTHENTICATION_REALM,
+    process::READONLY_HTTP_AUTHENTICATION_REALM);
+
+  // Now, schedule a new timer which is supposed to fire later than the one
+  // above.
+  Promise<Nothing> promise;
+  Future<Nothing> future = promise.future();
+
+  process::Timer timer_after = Clock::timer(Milliseconds(10),
+                                            [&]() { promise.set(Nothing()); });
+
+  // Wait until it fires.
+  AWAIT_READY(future);
+}