Skip to content

Commit 54c8016

Browse files
committed
ChildProcess: account for a system error when launching a process
When a non-existing command is attempted to run, both status and signal will be null, which leads to ChildProcess module crashing. Obviously, this is incorrect behavior. The problem is more general than that though: any system error that would result in failing to run a process would result in the module crash. Fix that by checking for such case. Fixes: #65
1 parent e78540b commit 54c8016

File tree

3 files changed

+16
-8
lines changed

3 files changed

+16
-8
lines changed

CHANGELOG.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ New features:
1010

1111
Bugfixes:
1212

13+
- Account for child creation to possibly fail with system error (#66 by @Hi-Angel)
14+
1315
Other improvements:
1416

1517
## [v11.1.0](https://github.com/purescript-node/purescript-node-child-process/releases/tag/v11.1.0) - 2023-11-14
@@ -76,7 +78,7 @@ Breaking changes:
7678
- Moved from `Node.ChildProces` to `Node.ChildProces.Types`
7779
- Changed the `BySignal`'s constructor's arg type from `Signal` to `String`
7880
- Breaking changes made to the `Handle` type (#46 by @JordanMartinez)
79-
81+
8082
- Moved from `Node.ChildProces` to `Node.ChildProces.Types`
8183
- Converted `defaultOptions { override = Just 1}` pattern to `(_ { override = Just 1})` (#46 by @JordanMartinez)
8284

src/Node/ChildProcess.purs

+8-4
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
-- | defined in this library that doesn't exist in the Node docs.
2222
-- | It exists to allow the end-user to append additional values to the `safeStdio` value
2323
-- | used here. For example,
24-
-- |
24+
-- |
2525
-- | ```
2626
-- | spawn' file args (_ { appendStdio = Just [ fileDescriptor8, pipe, pipe ]})
2727
-- | ```
@@ -86,7 +86,7 @@ module Node.ChildProcess
8686

8787
import Prelude
8888

89-
import Data.Maybe (Maybe(..), fromMaybe)
89+
import Data.Maybe (Maybe(..), fromMaybe, isJust)
9090
import Data.Nullable (Nullable, toMaybe, toNullable)
9191
import Data.Posix (Pid, Gid, Uid)
9292
import Data.Posix.Signal (Signal)
@@ -237,7 +237,9 @@ spawnSync command args = (UnsafeCP.spawnSync command args) <#> \r ->
237237
, exitStatus: case toMaybe r.status, toMaybe r.signal of
238238
Just c, _ -> Normally c
239239
_, Just s -> BySignal s
240-
_, _ -> unsafeCrashWith $ "Impossible: `spawnSync` child process neither exited nor was killed."
240+
_, _ -> if isJust $ toMaybe r.error
241+
then BySysError
242+
else unsafeCrashWith $ "Impossible: `spawnSync` child process neither exited nor was killed."
241243
, error: toMaybe r.error
242244
}
243245

@@ -282,7 +284,9 @@ spawnSync' command args buildOpts = (UnsafeCP.spawnSync' command args opts) <#>
282284
, exitStatus: case toMaybe r.status, toMaybe r.signal of
283285
Just c, _ -> Normally c
284286
_, Just s -> BySignal s
285-
_, _ -> unsafeCrashWith $ "Impossible: `spawnSync` child process neither exited nor was killed."
287+
_, _ -> if isJust $ toMaybe r.error
288+
then BySysError
289+
else unsafeCrashWith $ "Impossible: `spawnSync` child process neither exited nor was killed."
286290
, error: toMaybe r.error
287291
}
288292
where

src/Node/ChildProcess/Types.purs

+5-3
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ foreign import data StdIO :: Type
5252
-- | Note: when used with `stdin`, piping the parent stdin to this stream
5353
-- | will not cause the child process to terminate when that parent stdin stream
5454
-- | ends via `Ctrl+D` user input. Rather, the child process will hang
55-
-- | until the parent process calls `Stream.end` on the child process'
55+
-- | until the parent process calls `Stream.end` on the child process'
5656
-- | `stdin` stream. Since it's impossible to know when the user
5757
-- | inputs `Ctrl+D`, `inherit` should be used instead.
5858
pipe :: StdIO
@@ -140,12 +140,14 @@ customShell = unsafeCoerce
140140
-- | what options were used.
141141
foreign import data StringOrBuffer :: Type
142142

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

149150
instance showExit :: Show Exit where
150151
show (Normally x) = "Normally " <> show x
151152
show (BySignal sig) = "BySignal " <> (either show show $ fromKillSignal sig)
153+
show BySysError = "BySysError"

0 commit comments

Comments
 (0)