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

fastwsgi blocks OTHER threads from executing #51

Open
ibrewster opened this issue Jan 5, 2024 · 3 comments
Open

fastwsgi blocks OTHER threads from executing #51

ibrewster opened this issue Jan 5, 2024 · 3 comments

Comments

@ibrewster
Copy link

Calling fastwsgi.run should block the main thread, but release the GIL, allowing other threads to run (I/O wait). However, the observed behavior is that all threads are blocked, implying the GIL is not released while fastwsgi is waiting (though the actual issue may be different).

Observe the difference in behavior with this toy code when using fastwsgi.run vs. the development flask app.run

import threading, time
import fastwsgi

from flask import Flask

app = Flask(__name__)

@app.get('/')
def hello_world():
    return 'Hello, World!', 200


def dummy_thread():
    while True:
        print("Staying alive!")
        time.sleep(1)
 
if __name__ == '__main__':
    thread = threading.Thread(target=dummy_thread)
    thread.start()
    time.sleep(3) # Should print "Staying alive!" a number of times
    
    # This should block the main thread, but the "staying alive" thread should keep running
    # Using fastwsgi, all stops.
    fastwsgi.run(wsgi_app=app, host='0.0.0.0', port=5000)
    
    # Using the flask provided development server, the other thread continues as expected.
    # app.run(host='0.0.0.0', port=5000)

In many (most?) apps this would not be an issue, however it makes fastwsgi unusable in any application that requires some sort of background processing, such as my RaspberryPi app that provides a web server, but also listens for button presses.

@remittor
Copy link
Contributor

remittor commented Jan 10, 2024

import threading, time
import fastwsgi

from flask import Flask

app = Flask(__name__)

@app.get('/')
def hello_world():
    return 'Hello, World!', 200

def dummy_thread():
    while True:
        print("Staying alive!")
        time.sleep(1)

if __name__ == '__main__':
    thread = threading.Thread(target = dummy_thread)
    thread.start()
    time.sleep(3) # Should print "Staying alive!" a number of times

    srv = fastwsgi.server
    srv.host = '0.0.0.0'
    srv.port = 5000
    srv.loglevel = 6
    #srv.allow_keepalive = 0
    srv.hook_sigint = 1   # intercepting the SIGINT signal inside the REST API request handler
    srv.nowait = 2        # enabling periodic maintenance of REST API requests
    rc = srv.init(app)
    if rc != 0:
        print(f"ERROR: cannot init REST API server (err = {rc})")
        exit(rc)
    
    print(f"REST API server listening at http://{srv.host}:{srv.port}")
    
    while True:
        # processing REST API requests
        rc = srv.run()
        if rc != 0:
            print(f"REST API return code = {rc}")
            break
        # asynchronous task execution (without waiting for a REST API request)
        # do something in background
        time.sleep(0)
    
    srv.close()
    print("===== FastWSGI server finish =====")

@Louciole
Copy link

Louciole commented Jul 28, 2024

Hi guys !
I have the same issue as ibrewster, i would like to be able to run some websockets in the background, I understand that i can unblock my GIL with the proposed solution, but I have some issue with it :

  • srv.nowait = 2 does not have any sense since the value is just used once as a boolean in fastwsgi.py
  • It still does not loop by itself.

Is there a cleaner solution ?

@remittor
Copy link
Contributor

@Louciole , look this func:

PyObject * run_nowait(PyObject * self, PyObject * server)

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