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

Hypercorn runs with duplicated process #88

Closed
stevstrong opened this issue Oct 31, 2022 · 10 comments
Closed

Hypercorn runs with duplicated process #88

stevstrong opened this issue Oct 31, 2022 · 10 comments

Comments

@stevstrong
Copy link

stevstrong commented Oct 31, 2022

Hi all,

I am not sure whether this is really hypercorn issue, but could not imagine what else can be so please bear with me.

I am running a server with hypercorn on Ubuntu 20.04.

The problem is that it is runs with a duplicated process in background.

root     2278497  0.8  0.1  41872 33568 pts/7    S    10:03   0:00 /usr/bin/python3 /usr/local/bin/hypercorn -c config.toml main:app --reload
root     2278499  0.0  0.0  17304 11332 pts/7    S    10:03   0:00 /usr/bin/python3 -c from multiprocessing.resource_tracker import main;main(4)
root     2278500  0.7  0.1  41648 34148 pts/7    S    10:03   0:00 /usr/bin/python3 -c from multiprocessing.spawn import spawn_main; spawn_main(tracker_fd=5, pipe_handle=7) --multiprocessing-fork

The main process is 2278497, but there are duplicated processes 2278499 and 2278450.
This causes unwanted effects by executing twice the same tasks.

How can I avoid that?

EDIT
A minimal example:

# test_main.py
from fastapi import FastAPI

app = FastAPI()

@app.get("/")
async def root():
    return {"message": "Hello World"}

print("main module loaded.")

I then type:

sudo hypercorn test_main:app

and the stdout is:

main module loaded.
main module loaded.
[2022-11-02 15:08:45 +0100] [2364437] [INFO] Running on http://127.0.0.1:8000 (CTRL + C to quit)

If I use uvicorn the message is printed only one time, as expected:

$ sudo uvicorn test_main:app

main module loaded.
INFO:     Started server process [2364692]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
@stevstrong
Copy link
Author

I just provided a minimal example to reproduce the problem in the first post.

Anybody any idea?
Maybe it has to do with multiple python versions installed?

@synodriver
Copy link
Contributor

I guess that is because hypercorn fork before import, while uvicorn import first.

@stevstrong
Copy link
Author

Am I doing something wrong?
I just followed the getting started docs...

@pgjones
Copy link
Owner

pgjones commented Nov 3, 2022

This is expected - is it causing a problem? (Hypercorn runs with a minimum of 2 processes).

@stevstrong
Copy link
Author

stevstrong commented Nov 4, 2022

Well, yes, it causing a problem, as it executes two times the same procedure in parallel, which should be executed only once...

@stevstrong
Copy link
Author

stevstrong commented Nov 4, 2022

Is there any option which forces hypercorn to run only with one process?

@pgjones
Copy link
Owner

pgjones commented Nov 5, 2022

What does it actually execute twice though? I think it will log twice, but only one app worker will run - the other worker manages the reloading.

@stevstrong
Copy link
Author

stevstrong commented Nov 7, 2022

In the real application the main module includes some other modules, and some of the other modules start a separate thread (kind of background service).
This thread should have only one instance.
But if hypercorn includes twice the same module, then I will have twice the mentioned thread, which is unwanted.

@pgjones
Copy link
Owner

pgjones commented Nov 7, 2022

Ah, I see. I would consider it problematic for a module to create side effects (start a thread) when imported. Instead I suggest you start the thread actively and place that call within a startup function. If you are using Quart you can do something like this,

@app.before_serving
async def startup():
    start_background_service()

Edit: I see you are using FastAPI, in which case you can use a startup event https://fastapi.tiangolo.com/advanced/events/

@stevstrong
Copy link
Author

OK, it looks like a reasonable solution, thank you very much for your support.

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

No branches or pull requests

3 participants