-
Notifications
You must be signed in to change notification settings - Fork 290
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
Terminate my application with exit code #1074
Comments
abhinav
added a commit
to abhinav/fx
that referenced
this issue
Apr 29, 2023
Adds a regression test verifying the behavior described in uber-go#1074. An Fx program using App.Run, and shut down with Shutdowner.Shutdown and an explcit exit code, does not exit with the requested exit code. This test fails right now: ``` % go test --- FAIL: TestShutdownExitCode (0.01s) writer.go:40: [Fx] PROVIDE fx.Lifecycle <= go.uber.org/fx.New.func1() writer.go:40: [Fx] PROVIDE fx.Shutdowner <= go.uber.org/fx.(*App).shutdowner-fm() writer.go:40: [Fx] PROVIDE fx.DotGraph <= go.uber.org/fx.(*App).dotGraph-fm() writer.go:40: [Fx] INVOKE go.uber.org/fx/internal/e2e/shutdowner_run_exitcode.main.func1() writer.go:40: [Fx] RUNNING writer.go:40: [Fx] TERMINATED main_test.go:46: Error Trace: [..]/fx/internal/e2e/shutdowner_run_exitcode/main_test.go:46 Error: An error is expected but got nil. Test: TestShutdownExitCode FAIL exit status 1 FAIL go.uber.org/fx/internal/e2e/shutdowner_run_exitcode 0.016s ```
abhinav
added a commit
to abhinav/fx
that referenced
this issue
Apr 29, 2023
We added support for changing the exit code for a Shutdowner with the ExitCode option in uber-go#989, but this was somehow not respected by App.Run. This changes App.Run to use the same underlying machinery (`Wait()`) to decide on the exit code to use. Resolves uber-go#1074
abhinav
added a commit
to abhinav/fx
that referenced
this issue
Apr 29, 2023
Adds a regression test verifying the behavior described in uber-go#1074. An Fx program using App.Run, and shut down with Shutdowner.Shutdown and an explcit exit code, does not exit with the requested exit code. This test fails right now: ``` % go test --- FAIL: TestShutdownExitCode (0.01s) writer.go:40: [Fx] PROVIDE fx.Lifecycle <= go.uber.org/fx.New.func1() writer.go:40: [Fx] PROVIDE fx.Shutdowner <= go.uber.org/fx.(*App).shutdowner-fm() writer.go:40: [Fx] PROVIDE fx.DotGraph <= go.uber.org/fx.(*App).dotGraph-fm() writer.go:40: [Fx] INVOKE go.uber.org/fx/internal/e2e/shutdowner_run_exitcode.main.func1() writer.go:40: [Fx] RUNNING writer.go:40: [Fx] TERMINATED main_test.go:46: Error Trace: [..]/fx/internal/e2e/shutdowner_run_exitcode/main_test.go:46 Error: An error is expected but got nil. Test: TestShutdownExitCode FAIL exit status 1 FAIL go.uber.org/fx/internal/e2e/shutdowner_run_exitcode 0.016s ```
abhinav
added a commit
to abhinav/fx
that referenced
this issue
Apr 29, 2023
We added support for changing the exit code for a Shutdowner with the ExitCode option in uber-go#989, but this was somehow not respected by App.Run. This changes App.Run to use the same underlying machinery (`Wait()`) to decide on the exit code to use. Resolves uber-go#1074
abhinav
added a commit
to abhinav/fx
that referenced
this issue
Apr 29, 2023
Adds a test for calling Shutdown from an fx.Invoke. This is partially tested in uber-go#1075 already, but as reported in uber-go#1074, it doesn't work if Start is used. This adds a test for that case as well.
abhinav
added a commit
to abhinav/fx
that referenced
this issue
Apr 29, 2023
App.Start nils out the "last" signal recorded by signalReceivers, which it otherwise broadcasts to waiters if it was already received. This is unnecessary especially because there's a discrepancy in behavior of using App.Start vs App.Run when shutting down from fx.Invoke. Given a program that calls Shutdown from fx.Invoke, when we do: app := fx.New(...) The shutdowner has already sent the signal, and signalReceivers has already recorded it. At that point, whether we call App.Start or App.Run changes behavior: - If we call App.Run, that calls App.Done (or App.Wait after uber-go#1075), which gives it back a channel that already has the signal filled in. It then calls App.Start, waits on the channel--which returns immediately--and then calls App.Stop. - If we call App.Start and App.Wait, on the other hand, Start will clear the signal recorded in signalReceivers, and then App.Wait will build a channel that will block indefinitely because Shutdowner.Shutdown will not be called again. So even though App.Run() and App.Start()+App.Wait() are meant to be equivalent, this causes a serious discrepancy in behavior. It makes sense to resolve this by supporting Shutdown from Invoke. Refs uber-go#1074
abhinav
added a commit
to abhinav/fx
that referenced
this issue
Apr 29, 2023
Adds a test for calling Shutdown from an fx.Invoke. This is partially tested in uber-go#1075 already, but as reported in uber-go#1074, it doesn't work if Start is used. This adds a test for that case as well.
abhinav
added a commit
to abhinav/fx
that referenced
this issue
Apr 29, 2023
App.Start nils out the "last" signal recorded by signalReceivers, which it otherwise broadcasts to waiters if it was already received. This is unnecessary especially because there's a discrepancy in behavior of using App.Start vs App.Run when shutting down from fx.Invoke. Given a program that calls Shutdown from fx.Invoke, when we do: app := fx.New(...) The shutdowner has already sent the signal, and signalReceivers has already recorded it. At that point, whether we call App.Start or App.Run changes behavior: - If we call App.Run, that calls App.Done (or App.Wait after uber-go#1075), which gives it back a channel that already has the signal filled in. It then calls App.Start, waits on the channel--which returns immediately--and then calls App.Stop. - If we call App.Start and App.Wait, on the other hand, Start will clear the signal recorded in signalReceivers, and then App.Wait will build a channel that will block indefinitely because Shutdowner.Shutdown will not be called again. So even though App.Run() and App.Start()+App.Wait() are meant to be equivalent, this causes a serious discrepancy in behavior. It makes sense to resolve this by supporting Shutdown from Invoke. Refs uber-go#1074
sywhang
pushed a commit
that referenced
this issue
Apr 29, 2023
We added support for changing the exit code for a Shutdowner with the ExitCode option in #989, but this was somehow not respected by App.Run. This changes App.Run to use the same underlying machinery (`Wait()`) to decide on the exit code to use. To test this, we add a new internal/e2e submodule that will hold full, end-to-end integration tests. These can be full Fx applications that we run tests against. This is a submodule so that it can have dependencies that are not desirable as direct dependencies of Fx, and it's inside the internal/ directory so that it can consume Fx-internal packages (like testutil). The included regression test verifies the behavior described in #1074. An Fx program using App.Run, and shut down with Shutdowner.Shutdown and an explicit exit code, does not exit with the requested exit code. Failure before the fix: ``` % go test --- FAIL: TestShutdownExitCode (0.01s) writer.go:40: [Fx] PROVIDE fx.Lifecycle <= go.uber.org/fx.New.func1() writer.go:40: [Fx] PROVIDE fx.Shutdowner <= go.uber.org/fx.(*App).shutdowner-fm() writer.go:40: [Fx] PROVIDE fx.DotGraph <= go.uber.org/fx.(*App).dotGraph-fm() writer.go:40: [Fx] INVOKE go.uber.org/fx/internal/e2e/shutdowner_run_exitcode.main.func1() writer.go:40: [Fx] RUNNING writer.go:40: [Fx] TERMINATED main_test.go:46: Error Trace: [..]/fx/internal/e2e/shutdowner_run_exitcode/main_test.go:46 Error: An error is expected but got nil. Test: TestShutdownExitCode FAIL exit status 1 FAIL go.uber.org/fx/internal/e2e/shutdowner_run_exitcode 0.016s ``` Resolves #1074 --- There's a follow up to this: abhinav#1. It depends on the e2e test machinery, so I'll make a PR out of it once this is merged.
abhinav
added a commit
to abhinav/fx
that referenced
this issue
Apr 29, 2023
Adds a test for calling Shutdown from an fx.Invoke. This is partially tested in uber-go#1075 already, but as reported in uber-go#1074, it doesn't work if Start is used. This adds a test for that case as well.
abhinav
added a commit
to abhinav/fx
that referenced
this issue
Apr 29, 2023
App.Start nils out the "last" signal recorded by signalReceivers, which it otherwise broadcasts to waiters if it was already received. This is unnecessary especially because there's a discrepancy in behavior of using App.Start vs App.Run when shutting down from fx.Invoke. Given a program that calls Shutdown from fx.Invoke, when we do: app := fx.New(...) The shutdowner has already sent the signal, and signalReceivers has already recorded it. At that point, whether we call App.Start or App.Run changes behavior: - If we call App.Run, that calls App.Done (or App.Wait after uber-go#1075), which gives it back a channel that already has the signal filled in. It then calls App.Start, waits on the channel--which returns immediately--and then calls App.Stop. - If we call App.Start and App.Wait, on the other hand, Start will clear the signal recorded in signalReceivers, and then App.Wait will build a channel that will block indefinitely because Shutdowner.Shutdown will not be called again. So even though App.Run() and App.Start()+App.Wait() are meant to be equivalent, this causes a serious discrepancy in behavior. It makes sense to resolve this by supporting Shutdown from Invoke. Refs uber-go#1074
abhinav
added a commit
to abhinav/fx
that referenced
this issue
May 6, 2023
Adds a test for calling Shutdown from an fx.Invoke. This is partially tested in uber-go#1075 already, but as reported in uber-go#1074, it doesn't work if Start is used. This adds a test for that case as well.
abhinav
added a commit
to abhinav/fx
that referenced
this issue
May 6, 2023
App.Start nils out the "last" signal recorded by signalReceivers, which it otherwise broadcasts to waiters if it was already received. This is unnecessary especially because there's a discrepancy in behavior of using App.Start vs App.Run when shutting down from fx.Invoke. Given a program that calls Shutdown from fx.Invoke, when we do: app := fx.New(...) The shutdowner has already sent the signal, and signalReceivers has already recorded it. At that point, whether we call App.Start or App.Run changes behavior: - If we call App.Run, that calls App.Done (or App.Wait after uber-go#1075), which gives it back a channel that already has the signal filled in. It then calls App.Start, waits on the channel--which returns immediately--and then calls App.Stop. - If we call App.Start and App.Wait, on the other hand, Start will clear the signal recorded in signalReceivers, and then App.Wait will build a channel that will block indefinitely because Shutdowner.Shutdown will not be called again. So even though App.Run() and App.Start()+App.Wait() are meant to be equivalent, this causes a serious discrepancy in behavior. It makes sense to resolve this by supporting Shutdown from Invoke. Refs uber-go#1074
abhinav
added a commit
to abhinav/fx
that referenced
this issue
May 6, 2023
Adds a test for calling Shutdown from an fx.Invoke. This is partially tested in uber-go#1075 already, but as reported in uber-go#1074, it doesn't work if Start is used. This adds a test for that case as well.
abhinav
added a commit
to abhinav/fx
that referenced
this issue
May 6, 2023
App.Start nils out the "last" signal recorded by signalReceivers, which it otherwise broadcasts to waiters if it was already received. This is unnecessary especially because there's a discrepancy in behavior of using App.Start vs App.Run when shutting down from fx.Invoke. Given a program that calls Shutdown from fx.Invoke, when we do: app := fx.New(...) The shutdowner has already sent the signal, and signalReceivers has already recorded it. At that point, whether we call App.Start or App.Run changes behavior: - If we call App.Run, that calls App.Done (or App.Wait after uber-go#1075), which gives it back a channel that already has the signal filled in. It then calls App.Start, waits on the channel--which returns immediately--and then calls App.Stop. - If we call App.Start and App.Wait, on the other hand, Start will clear the signal recorded in signalReceivers, and then App.Wait will build a channel that will block indefinitely because Shutdowner.Shutdown will not be called again. So even though App.Run() and App.Start()+App.Wait() are meant to be equivalent, this causes a serious discrepancy in behavior. It makes sense to resolve this by supporting Shutdown from Invoke. Refs uber-go#1074
sywhang
added a commit
that referenced
this issue
May 8, 2023
Stacked on top of: - #1081 - #1082 However, since I can't push branches directly to this repository, this PR shows commits from all PRs. --- App.Start nils out the "last" signal recorded by signalReceivers, which it otherwise broadcasts to waiters if it was already received. This is unnecessary especially because there's a discrepancy in behavior of using App.Start vs App.Run when shutting down from fx.Invoke. Given a program that calls Shutdown from fx.Invoke, when we do: app := fx.New(...) The shutdowner has already sent the signal, and signalReceivers has already recorded it. At that point, whether we call App.Start or App.Run changes behavior: - If we call App.Run, that calls App.Done (or App.Wait after #1075), which gives it back a channel that already has the signal filled in. It then calls App.Start, waits on the channel--which returns immediately--and then calls App.Stop. - If we call App.Start and App.Wait, on the other hand, Start will clear the signal recorded in signalReceivers, and then App.Wait will build a channel that will block indefinitely because Shutdowner.Shutdown will not be called again. So even though App.Run() and App.Start()+App.Wait() are meant to be equivalent, this causes a serious discrepancy in behavior. It makes sense to resolve this by supporting Shutdown from Invoke. Refs #1074 --------- Co-authored-by: Sung Yoon Whang <[email protected]>
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Bug report from #1073
Discussed in #1073
Originally posted by nemliyartym April 28, 2023
Hi all. I would like to know how can I terminate my application with the exit codes I need. I have a simple
smb
module with a run function that callsshutdowner.Shutdown(fx.ExitCode(20))
with the code I need.If in main I just call
app.Run()
then my app exits with code 0. Do I test it withecho$?
. I changedRun
to callStart+Done+Stop
to try and get the exit code fromDone
, but that didn't work for me. I also tried to changeDone
toWait
, but in this case, the application hangs on the channel of wait.Please, tell me what am I doing wrong?)
main.go
smb.go
The text was updated successfully, but these errors were encountered: