Skip to content

Commit

Permalink
Remove exception throwing for pid in favor of returning -1
Browse files Browse the repository at this point in the history
  • Loading branch information
05nelsonm committed Feb 10, 2024
1 parent 33d8845 commit 5da6f71
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 36 deletions.
1 change: 0 additions & 1 deletion library/process/api/process.api
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ public abstract class io/matthewnelson/kmp/process/Process {
public abstract fun exitCode ()I
public final fun isAlive ()Z
public abstract fun pid ()I
public final fun pidOrNull ()Ljava/lang/Integer;
public abstract fun waitFor ()I
public abstract fun waitFor-LRDsOJo (J)Ljava/lang/Integer;
public final fun waitForAsync (Lkotlin/jvm/functions/Function2;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,20 +80,12 @@ public abstract class Process internal constructor(
/**
* Returns the [Process] id.
*
* @see [pidOrNull]
* @throws [UnsupportedOperationException] on Jvm if:
* **NOTE:** On Jvm this can return -1 (Unknown) if:
* - Unable to retrieve via `java.lang.Process.toString` output
* - `java.lang.Process.pid` method unavailable (Java 8 or Android Runtime)
* */
@Throws(UnsupportedOperationException::class)
public abstract fun pid(): Int

public fun pidOrNull(): Int? = try {
pid()
} catch (_: UnsupportedOperationException) {
null
}

/**
* Blocks the current thread until [Process] completion.
*
Expand Down Expand Up @@ -190,7 +182,7 @@ public abstract class Process internal constructor(
*
* e.g. (Executable file)
*
* val p = Process.Builder(myExecutableFile.absolutePath)
* val p = Process.Builder(myExecutableFile)
* .args("--some-flag")
* .args("someValue")
* .args("--another-flag", "anotherValue")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,32 @@ internal class JvmProcess private constructor(
private val jProcess: java.lang.Process,
): Process(command, args, env, stdio, destroy) {

private val _pid: Int by lazy {
// First try parsing toString output
jProcess.toString()
// Process[pid=1754008, exitValue="not exited"]
.substringAfter("pid=")
.substringBefore(']')
.substringBefore(',')
// "Bug" in Android may add a space after the pid value
// before the comma if there are more than 2 arguments.
.trim()
.toIntOrNull()
?.let { return@lazy it }

// Lastly try reflection
try {
val id = java.lang.Process::class.java
.getDeclaredMethod("pid")
.invoke(jProcess) as Long

return@lazy id.toInt()
} catch (_: Throwable) {}

// Unknown
-1
}

override fun destroy(): Process {
when (destroySignal) {
Signal.SIGTERM -> jProcess.destroy()
Expand Down Expand Up @@ -57,31 +83,7 @@ internal class JvmProcess private constructor(
return result ?: throw IllegalStateException("Process hasn't exited")
}

override fun pid(): Int {
// First try parsing toString output
jProcess.toString()
// Process[pid=1754008, exitValue="not exited"]
.substringAfter("pid=")
.substringBefore(']')
.substringBefore(',')
// "Bug" in Android may add a space after the pid value
// before the comma if there are more than 2 arguments.
.trim()
.toIntOrNull()
?.let { return it }

// Lastly try reflection
return try {
val id = java.lang.Process::class.java
.getDeclaredMethod("pid")
.invoke(jProcess) as Long

id.toInt()
} catch (t: Throwable) {
if (t is UnsupportedOperationException) throw t
throw UnsupportedOperationException("pid is not supported", t)
}
}
override fun pid(): Int = _pid

@Throws(InterruptedException::class)
override fun waitFor(): Int = jProcess.waitFor()
Expand Down

0 comments on commit 5da6f71

Please sign in to comment.