You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@linkis.apache.org by pe...@apache.org on 2022/09/16 03:05:45 UTC

[incubator-linkis] branch dev-1.3.1 updated: feat(common): remove use of sun.misc.Signal (#3337)

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

peacewong pushed a commit to branch dev-1.3.1
in repository https://gitbox.apache.org/repos/asf/incubator-linkis.git


The following commit(s) were added to refs/heads/dev-1.3.1 by this push:
     new b804c971e feat(common): remove use of sun.misc.Signal (#3337)
b804c971e is described below

commit b804c971e1954a384753a6cd63ba8655c3cb5265
Author: Jack Xu <xu...@126.com>
AuthorDate: Fri Sep 16 11:05:40 2022 +0800

    feat(common): remove use of sun.misc.Signal (#3337)
    
    * feat(common): remove use of sun.misc.Signal
---
 .../linkis/common/utils/ShutdownHookManager.scala  | 139 +++++++++++++++++++++
 .../apache/linkis/common/utils/ShutdownUtils.scala |  87 -------------
 .../org/apache/linkis/common/utils/Utils.scala     |   2 +-
 3 files changed, 140 insertions(+), 88 deletions(-)

diff --git a/linkis-commons/linkis-common/src/main/scala/org/apache/linkis/common/utils/ShutdownHookManager.scala b/linkis-commons/linkis-common/src/main/scala/org/apache/linkis/common/utils/ShutdownHookManager.scala
new file mode 100644
index 000000000..ace2973e6
--- /dev/null
+++ b/linkis-commons/linkis-common/src/main/scala/org/apache/linkis/common/utils/ShutdownHookManager.scala
@@ -0,0 +1,139 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.linkis.common.utils
+
+import java.util.PriorityQueue
+
+import org.slf4j.{Logger, LoggerFactory}
+
+private[linkis] object ShutdownHookManager {
+
+  val DEFAULT_SHUTDOWN_ORDER: Int = Int.MaxValue
+
+  private lazy val shutdownHooks = {
+    val manager = new LinkisShutdownHookManager()
+    manager.install()
+    manager
+  }
+
+  /**
+   * This detects whether the JVM is shutting down by Runtime#addShutdownHook throwing an
+   * IllegalStateException.
+   */
+  def inShutdown(): Boolean = {
+    try {
+      val hook = new Thread {
+        override def run(): Unit = {}
+      }
+      // scalastyle:off runtimeaddshutdownhook
+      Runtime.getRuntime.addShutdownHook(hook)
+      // scalastyle:on runtimeaddshutdownhook
+      Runtime.getRuntime.removeShutdownHook(hook)
+    } catch {
+      case _: IllegalStateException => return true
+    }
+    false
+  }
+
+  /**
+   * Adds a shutdown hook with default order.
+   *
+   * @param hook
+   *   The code to run during shutdown.
+   * @return
+   *   A handle that can be used to unregister the shutdown hook.
+   */
+  def addShutdownHook(hook: => Unit): LinkisShutdownHook = {
+    addShutdownHook(DEFAULT_SHUTDOWN_ORDER)(hook)
+  }
+
+  /**
+   * Adds a shutdown hook with the given order. Hooks with lower order values run first.
+   *
+   * @param hook
+   *   The code to run during shutdown.
+   * @return
+   *   A handle that can be used to unregister the shutdown hook.
+   */
+  def addShutdownHook(order: Int)(hook: => Unit): LinkisShutdownHook = {
+    shutdownHooks.add(order, hook)
+  }
+
+  /**
+   * Remove a previously installed shutdown hook.
+   *
+   * @param ref
+   *   A handle returned by `addShutdownHook`.
+   * @return
+   *   Whether the hook was removed.
+   */
+  def removeShutdownHook(ref: LinkisShutdownHook): Boolean = {
+    shutdownHooks.remove(ref)
+  }
+
+}
+
+private[utils] class LinkisShutdownHookManager {
+
+  private val hooks = new PriorityQueue[LinkisShutdownHook]()
+  @volatile private var shuttingDown = false
+
+  implicit val logger: Logger = LoggerFactory.getLogger(classOf[LinkisShutdownHookManager])
+
+  def install(): Unit = {
+    val hookTask = new Runnable() {
+      override def run(): Unit = runAll()
+    }
+    // scalastyle:off runtimeaddshutdownhook
+    Runtime.getRuntime.addShutdownHook(new Thread(hookTask))
+    // scalastyle:on runtimeaddshutdownhook
+  }
+
+  def runAll(): Unit = {
+    shuttingDown = true
+    var nextHook: LinkisShutdownHook = null
+    while ({ nextHook = hooks.synchronized { hooks.poll() }; nextHook != null }) {
+      Utils.tryAndWarn(nextHook.run())
+    }
+  }
+
+  def add(order: Int, hook: => Unit): LinkisShutdownHook = {
+    hooks.synchronized {
+      if (shuttingDown) {
+        throw new IllegalStateException("Shutdown hooks cannot be modified during shutdown.")
+      }
+      val hookRef = new LinkisShutdownHook(order, hook)
+      hooks.add(hookRef)
+      hookRef
+    }
+  }
+
+  def remove(ref: LinkisShutdownHook): Boolean = {
+    hooks.synchronized { hooks.remove(ref) }
+  }
+
+}
+
+private[linkis] class LinkisShutdownHook(private val priority: Int, hook: => Unit)
+    extends Comparable[LinkisShutdownHook] {
+
+  override def compareTo(other: LinkisShutdownHook): Int = priority.compareTo(other.priority)
+
+  def run(): Unit = hook
+
+}
diff --git a/linkis-commons/linkis-common/src/main/scala/org/apache/linkis/common/utils/ShutdownUtils.scala b/linkis-commons/linkis-common/src/main/scala/org/apache/linkis/common/utils/ShutdownUtils.scala
deleted file mode 100644
index 7fefb16ab..000000000
--- a/linkis-commons/linkis-common/src/main/scala/org/apache/linkis/common/utils/ShutdownUtils.scala
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *    http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.linkis.common.utils
-
-import scala.collection.mutable.ArrayBuffer
-
-import sun.misc.{Signal, SignalHandler}
-
-object ShutdownUtils {
-
-  private val shutdownRunners = ArrayBuffer[ShutdownRunner]()
-
-  def addShutdownHook(runnable: Runnable): Unit = addShutdownHook(Int.MaxValue, runnable)
-
-  def addShutdownHook(order: Int, runnable: Runnable): Unit =
-    shutdownRunners synchronized shutdownRunners += new DefaultShutdownRunner(order, runnable)
-
-  def addShutdownHook(hook: => Unit): Unit = addShutdownHook(Int.MaxValue, hook)
-
-  def addShutdownHook(order: Int, hook: => Unit): Unit =
-    shutdownRunners synchronized shutdownRunners += new FunctionShutdownRunner(order, hook)
-
-  def addShutdownHook(shutdownRunner: ShutdownRunner): Unit =
-    shutdownRunners synchronized shutdownRunners += shutdownRunner
-
-  private val signals = Array("TERM", "HUP", "INT")
-    .map(signal => Utils.tryQuietly(new Signal(signal)))
-    .filter(_ != null)
-
-  private val signalHandler = new SignalHandler {
-
-    override def handle(signal: Signal): Unit = {
-      val hooks = shutdownRunners.sortBy(_.order).toArray.map {
-        case m: DefaultShutdownRunner =>
-          Utils.defaultScheduler.execute(m)
-          m
-        case m =>
-          val runnable = new DefaultShutdownRunner(m.order, m)
-          Utils.defaultScheduler.execute(runnable)
-          runnable
-      }
-      val startTime = System.currentTimeMillis
-      ShutdownUtils synchronized {
-        while (System.currentTimeMillis - startTime < 30000 && hooks.exists(!_.isCompleted))
-          ShutdownUtils.wait(3000)
-      }
-      System.exit(0)
-    }
-
-  }
-
-  signals.foreach(Signal.handle(_, signalHandler))
-}
-
-trait ShutdownRunner extends Runnable {
-  val order: Int
-}
-
-class DefaultShutdownRunner(override val order: Int, runnable: Runnable) extends ShutdownRunner {
-  private var completed = false
-
-  override def run(): Unit = Utils.tryFinally(runnable.run()) {
-    completed = true
-    ShutdownUtils synchronized ShutdownUtils.notify()
-  }
-
-  def isCompleted: Boolean = completed
-}
-
-class FunctionShutdownRunner(override val order: Int, hook: => Unit) extends ShutdownRunner {
-  override def run(): Unit = hook
-}
diff --git a/linkis-commons/linkis-common/src/main/scala/org/apache/linkis/common/utils/Utils.scala b/linkis-commons/linkis-common/src/main/scala/org/apache/linkis/common/utils/Utils.scala
index 6a7a030fd..5f2361f48 100644
--- a/linkis-commons/linkis-common/src/main/scala/org/apache/linkis/common/utils/Utils.scala
+++ b/linkis-commons/linkis-common/src/main/scala/org/apache/linkis/common/utils/Utils.scala
@@ -322,7 +322,7 @@ object Utils extends Logging {
     lines.mkString("\n")
   }
 
-  def addShutdownHook(hook: => Unit): Unit = ShutdownUtils.addShutdownHook(hook)
+  def addShutdownHook(hook: => Unit): Unit = ShutdownHookManager.addShutdownHook(hook)
 
   def getClassInstance[T](className: String): T = {
     Utils.tryThrow(


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@linkis.apache.org
For additional commands, e-mail: commits-help@linkis.apache.org