Skip to content
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

Ensure non-zero exit code when startup fails #835

Closed
wants to merge 1 commit into from

Conversation

mboutet
Copy link

@mboutet mboutet commented Oct 23, 2020

Fixes #780

I think this is a pretty straightforward and minimal fix. I tested it in my app and it works.

I'm using uvicorn like this:

uvicorn \
  --host "0.0.0.0" \
  --port "${SERVER_PORT}" \
  --access-log \
  --log-level debug \
  --limit-concurrency "${UVICORN_LIMIT_CONCURRENCY:-30}" \
  --backlog "${UVICORN_BACKLOG:-2048}" \
  myapp.main:app

In other words, I don't use a supervisor or something like that, so I'm not sure if those use cases are covered.

Let me know what you think.

@hongquan
Copy link

hongquan commented Oct 25, 2020

Could you return the exit code which follow some existing conventions? https://github.com/sixty-north/exit-codes/blob/master/exit_codes/exit_codes.py#L87

In this case, I think the code 78 (configuration error) is relevant.

@mboutet
Copy link
Author

mboutet commented Oct 25, 2020

Personally, I don't really mind using another non-zero code other than 1. However, it would be inconsistent with other parts of the codebase such as:

uvicorn/uvicorn/main.py

Lines 373 to 379 in d78394e

if (config.reload or config.workers > 1) and not isinstance(app, str):
logger = logging.getLogger("uvicorn.error")
logger.warning(
"You must pass the application as an import string to enable 'reload' or "
"'workers'."
)
sys.exit(1)

To be consistent, this exit code should also be 78 and I don't think that changing this would be a good idea since some users might rely on this behaviour. If you search sys.exit( in the codebase, we can see that exit code 1 is always used, mainly in cases where some kind of configuration error happened (i.e. before the server startup).

Let's wait for other opinions, and I'll change it if there's a consensus.

@liketechnik
Copy link

I've personally had a similar, although different issue, where an exception in my startup handler did not cause uvicorn to return an exit code != 0.

Therefore the current fix would not only catch configuration errors, but also application level errors. So either the handling of startup errors needs to be more fine grained or it is impossible to report the specific error cause via the exit code, imo.

@pquentin
Copy link

@florimondmanca @euri10 What are your thoughts on this? I got confused today again by this: I thought my app was shutdown externally when the issue was in fact an internal startup failure in my own code.

@euri10
Copy link
Member

euri10 commented Apr 2, 2021

yes this should be definitely be dealt with, I'm not sure the 1 exit is the most sensible way though,
and I dont have the time right now but it's on the todo !

@florimondmanca
Copy link
Member

florimondmanca commented Apr 2, 2021

Could someone interested in moving this forward share some before/after output for Uvicorn's behavior?

Edit: Actually I understand the issue is that the output shows that there was an issue on startup (and Uvicorn shuts down accordingly), but exit code is currently still zero in that case, right?

Is there anything we need to consider for the GunicornWorker? Does that handle startup/shutdown events too?

This might cause some breakage in case people falsely rely on "error on startup exits as OK", so let's just make sure to release this in a minor bump.

@pquentin
Copy link

pquentin commented Apr 7, 2021

Edit: Actually I understand the issue is that the output shows that there was an issue on startup (and Uvicorn shuts down accordingly), but exit code is currently still zero in that case, right?

Right!

I don't know about GunicornWorker, sorry.

@mboutet
Copy link
Author

mboutet commented Apr 7, 2021

@florimondmanca, I'm using the uvicorn.workers.UvicornWorker with gunicorn and the exit code is nonzero when there's a failure during startup if that's what you're asking.

@euri10
Copy link
Member

euri10 commented Jun 7, 2021

Long time I haven't thought about his but what would be the difference with a raise click.Abort() here ? I know we're using sys.exit(1) everywhere else instead of this pattern in the codebase, I just wondered what difference this could make, if that could be an improvement over just sending exit ?

Also this covers the only case where uvicorn is ran without --relaod or --workers , this would need to be considered as well in fixing the issue.

And finally the gunicorn case, but I think you alreaduy answered that

All that to say also a test for this would be awesome.

@Kludex
Copy link
Member

Kludex commented Jul 9, 2021

Gunicorn exits with code 3 if boot (startup) fails, and we accepted #1077.
I believe, for practicality, uvicorn should also exit with code 3.

Would you guys agree? @florimondmanca @euri10

@Kludex
Copy link
Member

Kludex commented Dec 4, 2021

I'd like to speed up this, and I don't agree with the exit code. Let's continue on #1278.

@Kludex Kludex closed this Dec 4, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

uvicorn exit with success code on error in startup stage
7 participants