From dbcd8952a36a56c4abfc5170be0186273733d675 Mon Sep 17 00:00:00 2001 From: Matthew Nelson Date: Thu, 7 Mar 2024 03:45:18 -0500 Subject: [PATCH 1/2] Close unneeded descriptors on NativeProcess instantiation --- .../kmp/process/internal/stdio/StdioHandle.kt | 38 ++++++++++++------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/library/process/src/nativeMain/kotlin/io/matthewnelson/kmp/process/internal/stdio/StdioHandle.kt b/library/process/src/nativeMain/kotlin/io/matthewnelson/kmp/process/internal/stdio/StdioHandle.kt index cd1ab6f..0c1d15d 100644 --- a/library/process/src/nativeMain/kotlin/io/matthewnelson/kmp/process/internal/stdio/StdioHandle.kt +++ b/library/process/src/nativeMain/kotlin/io/matthewnelson/kmp/process/internal/stdio/StdioHandle.kt @@ -47,26 +47,36 @@ internal class StdioHandle private constructor( // This is invoked once and only once upon NativeProcess // instantiation (after fork occurs). We can do some descriptor - // clean up here and close unneeded pipe ends which were duped + // clean up here and close unneeded descriptors which were duped // in the child process and remain open over there. - if (stdoutFD is StdioDescriptor.Pipe) { - try { - stdoutFD.write.close() - } catch (_: IOException) {} - } - - if (stderrFD is StdioDescriptor.Pipe) { - try { - stderrFD.write.close() - } catch (_: IOException) {} - } + try { + if (stdinFD is StdioDescriptor.Pipe) { + // Leave write end open here in parent + stdinFD.read + } else { + stdinFD + }.close() + } catch (_: IOException) {} - if (stdinFD !is StdioDescriptor.Pipe) return@Instance null + try { + if (stdoutFD is StdioDescriptor.Pipe) { + // Leave read end open here in parent + stdoutFD.write + } else { + stdoutFD + }.close() + } catch (_: IOException) {} try { - stdinFD.read.close() + if (stderrFD is StdioDescriptor.Pipe) { + // Leave read end open here in parent + stderrFD.write + } else { + stdoutFD + }.close() } catch (_: IOException) {} + if (stdinFD !is StdioDescriptor.Pipe) return@Instance null if (stdinFD.isClosed) return@Instance null WriteStream.of(stdinFD) From 504f8eb41755219a5bded2d58539cd985d475c7e Mon Sep 17 00:00:00 2001 From: Matthew Nelson Date: Thu, 7 Mar 2024 03:59:56 -0500 Subject: [PATCH 2/2] Do not swallow close exceptions --- .../kmp/process/internal/stdio/StdioHandle.kt | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/library/process/src/nativeMain/kotlin/io/matthewnelson/kmp/process/internal/stdio/StdioHandle.kt b/library/process/src/nativeMain/kotlin/io/matthewnelson/kmp/process/internal/stdio/StdioHandle.kt index 0c1d15d..3990f9f 100644 --- a/library/process/src/nativeMain/kotlin/io/matthewnelson/kmp/process/internal/stdio/StdioHandle.kt +++ b/library/process/src/nativeMain/kotlin/io/matthewnelson/kmp/process/internal/stdio/StdioHandle.kt @@ -41,6 +41,7 @@ internal class StdioHandle private constructor( override val isClosed: Boolean get() = stdinFD.isClosed && stdoutFD.isClosed && stderrFD.isClosed private val lock = Lock() + private var threw: IOException? = null private val stdin: Instance = Instance(create = { // TODO: Issue #6 @@ -56,7 +57,10 @@ internal class StdioHandle private constructor( } else { stdinFD }.close() - } catch (_: IOException) {} + } catch (e: IOException) { + threw?.let { e.addSuppressed(it) } + threw = e + } try { if (stdoutFD is StdioDescriptor.Pipe) { @@ -65,7 +69,10 @@ internal class StdioHandle private constructor( } else { stdoutFD }.close() - } catch (_: IOException) {} + } catch (e: IOException) { + threw?.let { e.addSuppressed(it) } + threw = e + } try { if (stderrFD is StdioDescriptor.Pipe) { @@ -74,11 +81,13 @@ internal class StdioHandle private constructor( } else { stdoutFD }.close() - } catch (_: IOException) {} + } catch (e: IOException) { + threw?.let { e.addSuppressed(it) } + threw = e + } if (stdinFD !is StdioDescriptor.Pipe) return@Instance null if (stdinFD.isClosed) return@Instance null - WriteStream.of(stdinFD) }) @@ -130,11 +139,12 @@ internal class StdioHandle private constructor( private fun closeNoLock() { if (isClosed) return - var threw: IOException? = null + var threw: IOException? = threw try { stdinFD.close() } catch (e: IOException) { + if (threw != null) e.addSuppressed(threw) threw = e } try {