diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000..a55e7a1 --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml index be4bb8e..c261620 100644 --- a/.idea/gradle.xml +++ b/.idea/gradle.xml @@ -13,6 +13,7 @@ diff --git a/kommand-examples/timeout/build.gradle.kts b/kommand-examples/timeout/build.gradle.kts new file mode 100644 index 0000000..7b253f5 --- /dev/null +++ b/kommand-examples/timeout/build.gradle.kts @@ -0,0 +1,79 @@ +import org.gradle.nativeplatform.platform.internal.DefaultNativePlatform + +val currentPlatform: Platform = when { + DefaultNativePlatform.getCurrentOperatingSystem().isMacOsX && DefaultNativePlatform.getCurrentArchitecture().isAmd64 -> Platform.MACOS_X64 + DefaultNativePlatform.getCurrentOperatingSystem().isMacOsX && DefaultNativePlatform.getCurrentArchitecture().isArm64 -> Platform.MACOS_ARM64 + DefaultNativePlatform.getCurrentOperatingSystem().isLinux && DefaultNativePlatform.getCurrentArchitecture().isAmd64 -> Platform.LINUX_X64 + DefaultNativePlatform.getCurrentOperatingSystem().isLinux && DefaultNativePlatform.getCurrentArchitecture().isArm64 -> Platform.LINUX_ARM64 + DefaultNativePlatform.getCurrentOperatingSystem().isWindows && DefaultNativePlatform.getCurrentArchitecture().isAmd64 -> Platform.MINGW_X64 + else -> throw GradleException("Host OS is not supported in Kotlin/Native.") +} + +plugins { + kotlin("multiplatform") +} + +repositories { + mavenCentral() + gradlePluginPortal() +} + +kotlin { + jvm { + compilations.all { + kotlinOptions.jvmTarget = "17" + } + withJava() + testRuns["test"].executionTask.configure { + useJUnitPlatform() + } + } + + val nativeTarget = when (currentPlatform) { + Platform.MACOS_X64 -> macosX64() + Platform.MACOS_ARM64 -> macosArm64() + Platform.LINUX_X64 -> linuxX64() + Platform.LINUX_ARM64 -> linuxArm64() + Platform.MINGW_X64 -> mingwX64() + } + + nativeTarget.apply { + binaries { + executable { + entryPoint = "com.kgit2.kommand.main" + } + } + } + + applyDefaultHierarchyTemplate() + + sourceSets { + // add opt-in + all { + languageSettings.optIn("kotlinx.cinterop.UnsafeNumber") + languageSettings.optIn("kotlinx.cinterop.ExperimentalForeignApi") + languageSettings.optIn("kotlin.experimental.ExperimentalNativeApi") + languageSettings.optIn("kotlin.native.runtime.NativeRuntimeApi") + languageSettings.optIn("kotlin.ExperimentalStdlibApi") + } + + commonMain { + dependencies { + implementation(rootProject) + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.0-RC2") + implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.5.0") + } + } + } +} + +enum class Platform( + val archName: String +) { + MACOS_X64("x86_64-apple-darwin"), + MACOS_ARM64("aarch64-apple-darwin"), + LINUX_X64("x86_64-unknown-linux-gnu"), + LINUX_ARM64("aarch64-unknown-linux-gnu"), + MINGW_X64("x86_64-pc-windows-gnu"), + ; +} diff --git a/kommand-examples/timeout/src/appleMain/kotlin/com/kgit2/kommand/Main.kt b/kommand-examples/timeout/src/appleMain/kotlin/com/kgit2/kommand/Main.kt new file mode 100644 index 0000000..bceba8a --- /dev/null +++ b/kommand-examples/timeout/src/appleMain/kotlin/com/kgit2/kommand/Main.kt @@ -0,0 +1,60 @@ +package com.kgit2.kommand + +import com.kgit2.kommand.process.Command +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.IO +import kotlinx.coroutines.async +import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.withTimeout +import kotlinx.datetime.Clock + +fun main() = runBlocking(Dispatchers.Default) { + // Sleep with regular + val start = Clock.System.now() + val status = Command("sleep").arg("5").status() + println("status: $status elapsed: ${Clock.System.now() - start}") + + // Sleep with timeout detection and timeout determination + val start2 = Clock.System.now() + val child = Command("sleep").arg("5").spawn() + val childJob = async(Dispatchers.IO) { + runCatching { + child.wait() + }.onFailure { + println("child result: $it") + }.getOrNull() + } + runCatching { + withTimeout(3000) { + childJob.await() + } + }.onSuccess { + println("status: $it elapsed: ${Clock.System.now() - start2}") + }.onFailure { + child.kill() + println("status: $it elapsed: ${Clock.System.now() - start2}") + } + + // Sleep with timeout detection and determination that it will not timeout + val start3 = Clock.System.now() + val child2 = Command("sleep").arg("2").spawn() + val childJob2 = async(Dispatchers.IO) { + runCatching { + child2.wait() + }.onFailure { + println("child result: $it") + }.getOrNull() + } + runCatching { + withTimeout(3000) { + childJob2.await() + } + }.onSuccess { + println("status: $it elapsed: ${Clock.System.now() - start3}") + }.onFailure { + child2.kill() + println("status: $it elapsed: ${Clock.System.now() - start3}") + } + + Unit +} diff --git a/settings.gradle.kts b/settings.gradle.kts index d5c3a30..e5c99df 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -25,3 +25,4 @@ include(":kommand-examples") include(":kommand-examples:example1") include(":kommand-examples:example2") include(":kommand-examples:example3") +include(":kommand-examples:timeout")