1+ package org.ntqqrev.yogurt
2+
3+ import io.ktor.server.engine.*
4+ import io.ktor.server.plugins.di.dependencies
5+ import kotlinx.atomicfu.atomic
6+ import kotlinx.cinterop.ExperimentalForeignApi
7+ import kotlinx.cinterop.staticCFunction
8+ import kotlinx.coroutines.runBlocking
9+ import org.ntqqrev.acidify.AbstractBot
10+ import org.ntqqrev.acidify.offline
11+ import platform.posix.SIGINT
12+ import platform.posix.exit
13+ import platform.posix.signal
14+
15+ val botRef = atomic<AbstractBot ?>(null )
16+
17+ @OptIn(ExperimentalForeignApi ::class )
18+ actual fun EmbeddedServer <* , * >.onSigint (hook : () -> Unit ) {
19+ botRef.value = runBlocking { application.dependencies.resolve<AbstractBot >() }
20+ // On Linux targets, the shutdown hook gets unexpectedly overridden by Ktor's internal shutdown hook;
21+ // and `server.stop()` blocks forever on Linux,
22+ // so we have to use a `exit(0)` to force the process to exit immediately after the shutdown hook is executed.
23+ // See KTOR-9308 and KTOR-9309 for more details.
24+ signal(SIGINT , staticCFunction { _ ->
25+ println (" Received SIGINT, shutting down..." )
26+ runBlocking {
27+ botRef.value?.offline()
28+ }
29+ exit(0 )
30+ })
31+ }
0 commit comments