Skip to content

A node program that crashes exits with status 0 #385

Description

@gilramir

Repository: gren-lang/compiler
Found against: gren 0.6.6, node 22

Summary

Generate.Node.sandwich wraps the whole generated program in a try that
catches everything and calls console.error(e). It never sets an exit status,
so a program that died reports success:

$ node app
Error: Cannot perform mod 0. Division by zero error.
    at _Debug_crash (…)
    …
$ echo $?
0

Anything that decides whether a run worked by looking at the exit status — a
shell script, make, CI, a supervisor, a test harness, && — is told the
program succeeded. A crash in production is invisible to the thing whose job is
to notice it.

Reproduction

module Main exposing (main)

import Init
import Math
import Node
import Stream
import Task exposing (Task)


main : Node.SimpleProgram a
main =
    Node.defineSimpleProgram
        (\env -> Node.endSimpleProgram (emit env))


emit : Node.Environment -> Task Never {}
emit env =
    Stream.writeLineAsBytes (String.fromInt (Math.modBy 0 7)) env.stdout
        |> Task.map (\_ -> {})
        |> Task.onError (\_ -> Task.succeed {})
$ gren make Main --output=app
$ node app > /dev/null 2>&1 ; echo $?
0

Any other crash reaches the same place: Debug.todo, a failed Debug.log on a
cyclic value, a RangeError from deep non-tail recursion.

Cause

compiler/src/Generate/Node.hs:

sandwich :: Name.Name -> B.Builder -> B.Builder
sandwich moduleName javascript =
  let name = Name.toBuilder moduleName
   in [r|#!/usr/bin/env node

try {
|]
        <> javascript
        <> …
        <> [r|.init({});
}
catch (e)
{
console.error(e);
}
|]

The catch is what turns an uncaught exception — which node would otherwise
report and exit 1 for — into a printed message and a clean exit.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions