Skip to content

ChildProcess: account for a system error when launching a process #66

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

Merged
merged 2 commits into from
Mar 22, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ New features:

Bugfixes:

- Account for child creation to possibly fail with system error (#66 by @Hi-Angel)

Other improvements:

## [v11.1.0](https://github.com/purescript-node/purescript-node-child-process/releases/tag/v11.1.0) - 2023-11-14
Expand Down Expand Up @@ -76,7 +78,7 @@ Breaking changes:
- Moved from `Node.ChildProces` to `Node.ChildProces.Types`
- Changed the `BySignal`'s constructor's arg type from `Signal` to `String`
- Breaking changes made to the `Handle` type (#46 by @JordanMartinez)

- Moved from `Node.ChildProces` to `Node.ChildProces.Types`
- Converted `defaultOptions { override = Just 1}` pattern to `(_ { override = Just 1})` (#46 by @JordanMartinez)

Expand Down
1 change: 1 addition & 0 deletions bower.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
"package.json"
],
"dependencies": {
"purescript-aff": "^7.0.0",
"purescript-exceptions": "^6.0.0",
"purescript-node-event-emitter": "https://github.com/purescript-node/purescript-node-event-emitter.git#^3.0.0",
"purescript-foreign": "^7.0.0",
Expand Down
16 changes: 12 additions & 4 deletions src/Node/ChildProcess.purs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
-- | defined in this library that doesn't exist in the Node docs.
-- | It exists to allow the end-user to append additional values to the `safeStdio` value
-- | used here. For example,
-- |
-- |
-- | ```
-- | spawn' file args (_ { appendStdio = Just [ fileDescriptor8, pipe, pipe ]})
-- | ```
Expand Down Expand Up @@ -86,7 +86,7 @@ module Node.ChildProcess

import Prelude

import Data.Maybe (Maybe(..), fromMaybe)
import Data.Maybe (Maybe(..), fromMaybe, isJust)
import Data.Nullable (Nullable, toMaybe, toNullable)
import Data.Posix (Pid, Gid, Uid)
import Data.Posix.Signal (Signal)
Expand Down Expand Up @@ -237,7 +237,11 @@ spawnSync command args = (UnsafeCP.spawnSync command args) <#> \r ->
, exitStatus: case toMaybe r.status, toMaybe r.signal of
Just c, _ -> Normally c
_, Just s -> BySignal s
_, _ -> unsafeCrashWith $ "Impossible: `spawnSync` child process neither exited nor was killed."
_, _ ->
if isJust $ toMaybe r.error then
BySysError
else
unsafeCrashWith $ "Impossible: `spawnSync` child process neither exited nor was killed."
, error: toMaybe r.error
}

Expand Down Expand Up @@ -282,7 +286,11 @@ spawnSync' command args buildOpts = (UnsafeCP.spawnSync' command args opts) <#>
, exitStatus: case toMaybe r.status, toMaybe r.signal of
Just c, _ -> Normally c
_, Just s -> BySignal s
_, _ -> unsafeCrashWith $ "Impossible: `spawnSync` child process neither exited nor was killed."
_, _ ->
if isJust $ toMaybe r.error then
BySysError
else
unsafeCrashWith $ "Impossible: `spawnSync` child process neither exited nor was killed."
, error: toMaybe r.error
}
where
Expand Down
8 changes: 5 additions & 3 deletions src/Node/ChildProcess/Types.purs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ foreign import data StdIO :: Type
-- | 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'
-- | 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
Expand Down Expand Up @@ -140,12 +140,14 @@ customShell = unsafeCoerce
-- | what options were used.
foreign import data StringOrBuffer :: Type

-- | Specifies how a child process exited; normally (with an exit code), or
-- | due to a signal.
-- | Specifies how a child process exited; normally (with an exit code), due to
-- | a signal or if it failed to even launch (e.g. if a command doesn't exist).
data Exit
= Normally Int
| BySignal KillSignal
| BySysError

instance showExit :: Show Exit where
show (Normally x) = "Normally " <> show x
show (BySignal sig) = "BySignal " <> (either show show $ fromKillSignal sig)
show BySysError = "BySysError"
1 change: 1 addition & 0 deletions test/Main.purs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ spawnLs = do
Normally 0 -> log $ "ls exited with 0"
Normally i -> liftEffect $ throw $ "ls had non-zero exit: " <> show i
BySignal sig -> liftEffect $ throw $ "ls exited with sig: " <> show sig
BySysError -> liftEffect $ throw "ls exited with system error"

nonExistentExecutable :: Aff Unit
nonExistentExecutable = do
Expand Down