-
-
Notifications
You must be signed in to change notification settings - Fork 2
Add tryWait() to Child class #21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -117,16 +117,33 @@ impl<E: Display> From<Result<Option<String>, E>> for VoidResult { | |
| impl From<io::Result<std::process::ExitStatus>> for IntResult { | ||
| fn from(value: io::Result<std::process::ExitStatus>) -> Self { | ||
| match value { | ||
| Ok(status) => match status.code() { | ||
| Ok(status) => Ok(Some(status)), | ||
| Err(e) => Err(e), | ||
| } | ||
| .into() | ||
| } | ||
| } | ||
|
|
||
| impl From<io::Result<Option<std::process::ExitStatus>>> for IntResult { | ||
| fn from(value: io::Result<Option<std::process::ExitStatus>>) -> Self { | ||
| match value { | ||
| Ok(status) => match status { | ||
| None => IntResult { | ||
| ok: -1, | ||
| err: into_cstring("No exit code"), | ||
| ok: -2, | ||
| err: into_cstring("Application still running"), | ||
| error_type: ErrorType::None, | ||
|
Comment on lines
+132
to
134
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add new ErrorType variant for "Application still running" |
||
| }, | ||
| Some(code) => IntResult { | ||
| ok: code, | ||
| err: std::ptr::null_mut() as *mut c_char, | ||
| error_type: ErrorType::None, | ||
| Some(status) => match status.code() { | ||
| None => IntResult { | ||
| ok: -1, | ||
| err: into_cstring("No exit code"), | ||
| error_type: ErrorType::None, | ||
| }, | ||
| Some(code) => IntResult { | ||
| ok: code, | ||
| err: std::ptr::null_mut() as *mut c_char, | ||
| error_type: ErrorType::None, | ||
| }, | ||
| }, | ||
| }, | ||
| Err(e) => IntResult { | ||
|
|
||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think there should be a special test mechanism for tryWait, such as executing a process lasting 5 seconds through Command, and calling tryWait periodically with 1 second, and you should expect 5 nulls and 1 ok. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,6 +5,7 @@ import com.kgit2.kommand.exception.KommandException | |
| import com.kgit2.kommand.io.BufferedReader | ||
| import com.kgit2.kommand.io.BufferedWriter | ||
| import com.kgit2.kommand.io.Output | ||
| import java.util.concurrent.TimeUnit | ||
| import java.util.concurrent.atomic.AtomicReference | ||
|
|
||
| actual class Child( | ||
|
|
@@ -45,6 +46,14 @@ actual class Child( | |
| return process.waitFor() | ||
| } | ||
|
|
||
| @Throws(KommandException::class) | ||
| actual fun tryWait(): Int? { | ||
| return when (process.waitFor(0, TimeUnit.MICROSECONDS)) { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why not use /**
* Returns the exit value for the process.
*
* @return the exit value of the process represented by this
* {@code Process} object. By convention, the value
* {@code 0} indicates normal termination.
* @throws IllegalThreadStateException if the process represented
* by this {@code Process} object has not yet terminated
*/
public abstract int exitValue();
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| true -> wait() | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same question as |
||
| false -> null | ||
| } | ||
| } | ||
|
|
||
| @Throws(KommandException::class) | ||
| actual fun waitWithOutput(): Output { | ||
| stdin.get()?.close() | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -9,12 +9,7 @@ import kommand_core.drop_output | |||||
| import kommand_core.drop_string | ||||||
| import kommand_core.into_output | ||||||
| import kommand_core.void_to_string | ||||||
| import kotlinx.cinterop.ByteVar | ||||||
| import kotlinx.cinterop.CPointer | ||||||
| import kotlinx.cinterop.CValue | ||||||
| import kotlinx.cinterop.memScoped | ||||||
| import kotlinx.cinterop.pointed | ||||||
| import kotlinx.cinterop.toKString | ||||||
| import kotlinx.cinterop.* | ||||||
|
|
||||||
| fun CPointer<ByteVar>.asString(): String { | ||||||
| val result = this.toKString() | ||||||
|
|
@@ -53,6 +48,15 @@ fun Output.Companion.from(result: CValue<kommand_core.VoidResult>): Output = mem | |||||
| } | ||||||
| } | ||||||
|
|
||||||
| fun Int.Companion.fromOptional(result: CValue<kommand_core.IntResult>): Int? = memScoped { | ||||||
| return@memScoped if (result.ptr.pointed.ok == -2) { | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| // Application still running | ||||||
| null | ||||||
| } else { | ||||||
| Int.Companion.from(result) | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| @Throws(KommandException::class) | ||||||
| fun Int.Companion.from(result: CValue<kommand_core.IntResult>): Int = memScoped { | ||||||
| if (result.ptr.pointed.err != null) { | ||||||
|
|
||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,19 +2,14 @@ package com.kgit2.kommand.process | |
|
|
||
| import com.kgit2.kommand.exception.KommandException | ||
| import com.kgit2.kommand.from | ||
| import com.kgit2.kommand.fromOptional | ||
| import com.kgit2.kommand.io.BufferedReader | ||
| import com.kgit2.kommand.io.BufferedWriter | ||
| import com.kgit2.kommand.io.Output | ||
| import com.kgit2.kommand.io.ReaderType | ||
| import com.kgit2.kommand.unwrap | ||
| import kommand_core.buffered_stderr_child | ||
| import kommand_core.buffered_stdin_child | ||
| import kommand_core.buffered_stdout_child | ||
| import kommand_core.drop_child | ||
| import kommand_core.id_child | ||
| import kommand_core.kill_child | ||
| import kommand_core.wait_child | ||
| import kommand_core.wait_with_output_child | ||
| import kommand_core.* | ||
| import kommand_core.try_wait_child | ||
| import kotlinx.atomicfu.atomic | ||
| import kotlinx.atomicfu.locks.SynchronizedObject | ||
| import kotlinx.cinterop.COpaquePointer | ||
|
|
@@ -23,7 +18,7 @@ import kotlin.native.ref.createCleaner | |
|
|
||
| actual class Child( | ||
| private var inner: COpaquePointer? | ||
| ): SynchronizedObject() { | ||
| ) : SynchronizedObject() { | ||
| private var stdin: AtomicReference<BufferedWriter?> = AtomicReference(null) | ||
| private var stdout: AtomicReference<BufferedReader?> = AtomicReference(null) | ||
| private var stderr: AtomicReference<BufferedReader?> = AtomicReference(null) | ||
|
|
@@ -68,6 +63,15 @@ actual class Child( | |
| Int.from(wait_child(inner)) | ||
| } | ||
|
|
||
| @Throws(KommandException::class) | ||
| actual fun tryWait(): Int? { | ||
| val result = Int.fromOptional(try_wait_child(inner)) | ||
| return when (result) { | ||
| null -> null | ||
| else -> wait() | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. According to the rust try_wait example, when an error occurs in try_wait, it should be up to the caller to choose whether to do a blocking wait, and it seems that it should not be handled by default in the library. use std::process::Command;
let mut child = Command::new("ls").spawn().unwrap();
match child.try_wait() {
Ok(Some(status)) => println!("exited with: {status}"),
Ok(None) => {
println!("status not ready yet, let's really wait");
let res = child.wait();
println!("result: {res:?}");
}
Err(e) => println!("error attempting to wait: {e}"),
} |
||
| } | ||
| } | ||
|
|
||
| @Throws(KommandException::class) | ||
| actual fun waitWithOutput(): Output = run { | ||
| stdin.getAndSet(null)?.close() | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.