Skip to content

Commit

Permalink
Add note about stdin, pipe, and inherit (#62)
Browse files Browse the repository at this point in the history
* Add note about stdin, pipe, and inherit

See purescript/spago#1048

* Drop unused functions

* Add variant of waitSpawned
  • Loading branch information
JordanMartinez authored Nov 14, 2023
1 parent 12932f4 commit 99fd379
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 6 deletions.
22 changes: 16 additions & 6 deletions src/Node/ChildProcess/Aff.purs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -19,21 +20,30 @@ 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
removeListener

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
Expand Down
20 changes: 20 additions & 0 deletions src/Node/ChildProcess/Types.purs
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand All @@ -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"

Expand Down

0 comments on commit 99fd379

Please sign in to comment.