Skip to content

Conversation

blaix
Copy link
Contributor

@blaix blaix commented Aug 2, 2025

Working on #341

src/Main.gren Outdated
RunExited exitCode ->
let
_ =
Debug.log "Exited" {}
Copy link
Contributor Author

@blaix blaix Aug 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I never see this fire if the program I'm running reads from stdin. For example, this program works fine:

main =
    Node.defineSimpleProgram <| \env ->
        Stream.Log.line env.stdout "Done"
            |> Node.endSimpleProgram

gren run Main will show the Exited log and exit.

But this one will hang after hitting enter and never show the Exited log:

main =
    Node.defineSimpleProgram <| \env ->
        Stream.readBytesAsString env.stdin
            |> Task.onError (\_ -> Task.succeed "")
            |> Node.endSimpleProgram

But if you run the same program directly (node .gren/app) the program does not hang.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I know what's going on.

                        [ Task.succeed { source = output, target = model.stdout }
                        , Task.succeed { source = model.stdin, target = input }
                        , Task.succeed { source = error, target = model.stderr }
                        ]
                            |> Array.map (Task.attempt RedirectTerminalIO)
                            |> Cmd.batch

RedirectTerminalIO will call Stream.read on model.stdin twice, once for the compiler, then again for the program to run.

The second time Stream.read is called, it will fail with a Locked error (as we're still waiting for the Stream.read to finish from the compilation. The program will never receive a message on its stdin, as the Stream.read has failed.

I think we need to handle stdin specially.

I would create a RedirectStdin message, which begins by calling Stream.read model.stdin. Once/if we get some data from stdin, we can pass that content on to model.stdinRedirectTarget (or something) which is a Maybe Stream.Writable.

Copy link
Contributor Author

@blaix blaix Aug 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe I'm misunderstanding you, but the program does receive stdin. For example:

main =
    Node.defineSimpleProgram <| \env ->
        Stream.readBytesAsString env.stdin
            |> Task.onError (\_ -> Task.succeed "")
            |> Task.andThen (Stream.Log.line env.stdout)
            |> Node.endSimpleProgram

If I enter text it will print, but still hang and never show the Exited log.

Regardless, I still think it's worth trying to handle stdin redirection separately. I'll give it a shot.

Copy link
Contributor Author

@blaix blaix Aug 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering if what I want is a connection type for spawn that results in node calling the child process with detached: true and stdio: inherit. That seems to be how you'd get the behavior I want: "spawn this with shared stdio but let the parent program exit" and wouldn't require run to do any stdio redirection.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, actually Integrated seems to be doing what I want. Going to do some more testing and cleanup and get a real PR out ready for review, might take until sometime tomorrow.

blaix added 2 commits August 4, 2025 06:18
The streams that were being passed are never used.
@blaix
Copy link
Contributor Author

blaix commented Aug 4, 2025

Going to open a new PR for a clean review of the fix

@blaix blaix closed this Aug 4, 2025
@blaix blaix deleted the run-stdin-fix branch August 4, 2025 18:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants