Signals in Kotlin
Here’s the translation of the Go code to Kotlin, with explanations adapted for Kotlin and formatted in Markdown suitable for Hugo:
Our first program demonstrates how to handle signals in Kotlin. Here’s the full source code:
import kotlinx.coroutines.*
import kotlin.system.exitProcess
import kotlin.concurrent.thread
import java.util.concurrent.CountDownLatch
import sun.misc.Signal
fun main() = runBlocking {
// Kotlin doesn't have a direct equivalent to Go's signal.Notify,
// so we'll use Java's sun.misc.Signal class for signal handling
val sigs = Channel<String>(1)
// Register handlers for SIGINT and SIGTERM
listOf("INT", "TERM").forEach { signalName ->
Signal.handle(Signal(signalName)) { signal ->
runBlocking {
sigs.send(signal.name)
}
}
}
// We'll use a CountDownLatch to demonstrate a more realistic
// scenario of graceful shutdown
val done = CountDownLatch(1)
// This coroutine executes a blocking receive for signals.
// When it gets one, it'll print it out and then notify
// the program that it can finish.
launch {
val sig = sigs.receive()
println()
println(sig)
done.countDown()
}
// The program will wait here until it gets the expected signal
// (as indicated by the coroutine above counting down the latch)
// and then exit.
println("awaiting signal")
done.await()
println("exiting")
exitProcess(0)
}
When we run this program, it will block waiting for a signal. By typing ctrl-C
(which the terminal shows as ^C
), we can send a SIGINT
signal, causing the program to print INT
and then exit.
$ kotlinc -cp .:kotlinx-coroutines-core-1.5.2.jar SignalHandler.kt -include-runtime -d SignalHandler.jar
$ java -jar SignalHandler.jar
awaiting signal
^C
INT
exiting
Note that signal handling in Kotlin is not as straightforward as in Go, and we had to use Java’s sun.misc.Signal
class, which is not a standard API and may not be available on all Java implementations. In a production environment, you might want to consider using a more robust solution for signal handling.
Also, remember that Kotlin coroutines are used here as an analog to Go’s goroutines, providing a way to handle concurrency in a more idiomatic Kotlin style.