diff --git a/src/Node/ChildProcess/Aff.purs b/src/Node/ChildProcess/Aff.purs index 8eac411..8a43525 100644 --- a/src/Node/ChildProcess/Aff.purs +++ b/src/Node/ChildProcess/Aff.purs @@ -8,8 +8,9 @@ import Data.Maybe (fromJust) import Data.Posix (Pid) import Effect.Aff (Aff, effectCanceler, makeAff) import Effect.Ref as Ref -import Node.ChildProcess (ChildProcess, pid) -import Node.ChildProcess as CP +import Node.ChildProcess.Types (UnsafeChildProcess) +import Node.UnsafeChildProcess.Safe as CPSafe +import Node.ChildProcess (ChildProcess, toUnsafeChildProcess) import Node.Errors.SystemError (SystemError) import Node.EventEmitter (once) import Partial.Unsafe (unsafePartial) @@ -19,13 +20,22 @@ import Partial.Unsafe (unsafePartial) -- | and the `pid` of the process can be obtained. -- | If an `error` event fires, child process was not started successfully. waitSpawned :: ChildProcess -> Aff (Either SystemError Pid) -waitSpawned cp = parOneOf [ pidOnSpawn, errored ] +waitSpawned = toUnsafeChildProcess >>> waitSpawned' + +-- | Same as `waitSpawned` but works on `UnsafeChildProcess` +-- | +-- | Blocks until either a `spawn` or `error` event is fired. +-- | If a `spawn` event fired, child process was successfully started +-- | and the `pid` of the process can be obtained. +-- | If an `error` event fires, child process was not started successfully. +waitSpawned' :: UnsafeChildProcess -> Aff (Either SystemError Pid) +waitSpawned' cp = parOneOf [ pidOnSpawn, errored ] where pidOnSpawn = makeAff \done -> do ref <- Ref.new mempty - removeListener <- cp # once CP.spawnH do + removeListener <- cp # once CPSafe.spawnH do join $ Ref.read ref - pid' <- pid cp + pid' <- CPSafe.pid cp done $ Right $ Right $ unsafePartial $ fromJust pid' Ref.write removeListener ref pure $ effectCanceler do @@ -33,7 +43,7 @@ waitSpawned cp = parOneOf [ pidOnSpawn, errored ] errored = makeAff \done -> do ref <- Ref.new mempty - removeListener <- cp # once CP.errorH \sysErr -> do + removeListener <- cp # once CPSafe.errorH \sysErr -> do join $ Ref.read ref done $ Right $ Left sysErr Ref.write removeListener ref diff --git a/src/Node/ChildProcess/Types.purs b/src/Node/ChildProcess/Types.purs index dd3a74b..98f1370 100644 --- a/src/Node/ChildProcess/Types.purs +++ b/src/Node/ChildProcess/Types.purs @@ -44,6 +44,17 @@ foreign import data Handle :: Type -- | See https://nodejs.org/docs/latest-v18.x/api/child_process.html#optionsstdio foreign import data StdIO :: Type +-- | When used for X, then Y will exist on the child process where X and Y are +-- | - `stdio[0]` - `stdin` +-- | - `stdio[1]` - `stdout` +-- | - `stdio[2]` - `stderr` +-- | +-- | Note: when used with `stdin`, piping the parent stdin to this stream +-- | will not cause the child process to terminate when that parent stdin stream +-- | ends via `Ctrl+D` user input. Rather, the child process will hang +-- | until the parent process calls `Stream.end` on the child process' +-- | `stdin` stream. Since it's impossible to know when the user +-- | inputs `Ctrl+D`, `inherit` should be used instead. pipe :: StdIO pipe = unsafeCoerce "pipe" @@ -56,6 +67,15 @@ overlapped = unsafeCoerce "overlapped" ipc :: StdIO ipc = unsafeCoerce "ipc" +-- | Uses the parent's corresponding stream. +-- | +-- | Note: this value must be used for `stdin` if one +-- | wants to pipe the parent's `stdin` into the child process' `stdin` +-- | AND cause the child process to terminate when the user closes +-- | the parent's `stdin` via `Ctrl+D`. Using `pipe` instead +-- | will cause the child process to hang, even when `Ctrl+D` is pressed, +-- | until the parent process calls `Stream.end`, which cannot be reliably +-- | called the moment AFTER `Ctrl+D` is pressed. inherit :: StdIO inherit = unsafeCoerce "inherit"