Flask-socketio: ERROR - timed out

Created on 22 Mar 2018  路  3Comments  路  Source: miguelgrinberg/Flask-SocketIO

Windows 10 Enterprise
Python 2.7.13
Flask-SocketIO 2.8.6

Hi there,

I'm trying to create Windows Service using Flask-SocketIO. I'm able to create WIndows Service with name "TestFlaskService". And When I start this Windows service, Flask-SocketIO service is starting and I'm able to access on browser. I'm able to stop the Windows service even and it's stopping Flask-SocketIO Service.

But the problem I face is Flask-SocketIO is running only for 15 minutes through Windows Service and then it's throwing ERROR - timed out. I've put the stacktrace at end.

Below is the code for the Windows Service creation code.

WindowsServiceCreation.py

from run import run_service

from multiprocessing import Process
import win32serviceutil
import win32service
import win32event
import servicemanager
import socket
import os, signal
import subprocess

import logging

logging.basicConfig(
    filename='Windows-Service.log',
    level=logging.DEBUG,
    format='%(asctime)s - %(levelname)s - %(message)s'
)

class AppServerSvc (win32serviceutil.ServiceFramework):
    _svc_name_ = "TestFlaskService"
    _svc_display_name_ = "TestFlaskService"

    def __init__(self,args):
        win32serviceutil.ServiceFramework.__init__(self,args)
        self.hWaitStop = win32event.CreateEvent(None,0,0,None)
        socket.setdefaulttimeout(60)
        self.server = None

    def SvcStop(self):
        try:
            logging.info("Initiated Stopping....")
            pid = self.getPID()
            self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
            logging.info("Service Stop pending done...!")
            win32event.SetEvent(self.hWaitStop)

            if pid:
                self.ReportServiceStatus(win32service.SERVICE_STOPPED)
                logging.info("Got PID : " + str(pid))
                logging.info("+++++++++++++++ Server Stopped +++++++++++++++")
                os.kill(pid, signal.SIGTERM)
                logging.info("Killed the process")
            else:
                logging.info("+++++++++++++++ NO PID FOUND FOR GIVEN PORT "+self.getPort()+" +++++++++++++++")

        except Exception as e:
            logging.exception(e)


    def SvcDoRun(self):
        servicemanager.LogMsg(servicemanager.EVENTLOG_INFORMATION_TYPE,
                              servicemanager.PYS_SERVICE_STARTED,
                              (self._svc_name_,''))
        self.main()

    def main(self):
        try:
            logging.info("---------------- Starting Server ----------------")
            self.server = Process(target = run_service())
            #below lines are not being executed. Server is started in above line itself.
            self.server.start()
            self.server.run()
            logging.info("---------------- Server started ----------------")
        except Exception as e:
            logging.exception(e)

    def getPort(self):
        from app.utils.config import server_port
        return str(server_port)

    def getPID(self):
        port = self.getPort()
        command_line = 'netstat -a -n -o | find "' + port + '"'
        print command_line
        result = ''
        process = subprocess.Popen(command_line,
                                   shell=True,
                                   stdout=subprocess.PIPE,
                                   stderr=subprocess.PIPE)
        errcode = process.returncode
        if errcode is None:
            for line in process.stdout:
                if ('0.0.0.0:' + port in line or '127.0.0.1:' + port) and '0.0.0.0:0' in line and 'LISTENING' in line:
                    result += line
        if 'LISTENING' and port in result:
            parts = result.split()
            return int(parts[-1])
        else:
            return None


if __name__ == '__main__':
    win32serviceutil.HandleCommandLine(AppServerSvc)

run.py

from app import app
from app.utils.config import server_ip, server_port, is_debug_enabled
from app.celery_app import celery
from app.utils import Logger

from app.celery_app import socketio


def run_service():
    Logger.Infolog('Applog', 'Starting Server...')
    socketio.init_app(app)
    print "Running with", socketio.async_mode
    Logger.Infolog('Applog', "Running with " + socketio.async_mode)
    socketio.run(app, host=server_ip, port=server_port)

if __name__ == '__main__':
    run_service()
2018-03-22 12:47:02,855 - ERROR - timed out
Traceback (most recent call last):
  File "D:\Projects\AFA\AFA\WindowsService.py", line 68, in main
    run_service()
  File "D:\Projects\AFA\AFA\run.py", line 26, in run_service
    socketio.run(app, host=server_ip, port=server_port)
  File "C:\Anaconda2\lib\site-packages\flask_socketio\__init__.py", line 495, in run
    run_server()
  File "C:\Anaconda2\lib\site-packages\flask_socketio\__init__.py", line 490, in run_server
    log_output=log_output, **kwargs)
  File "C:\Anaconda2\lib\site-packages\eventlet\wsgi.py", line 896, in server
    client_socket = sock.accept()
  File "C:\Anaconda2\lib\site-packages\eventlet\greenio\base.py", line 224, in accept
    self._trampoline(fd, read=True, timeout=self.gettimeout(), timeout_exc=_timeout_exc)
  File "C:\Anaconda2\lib\site-packages\eventlet\greenio\base.py", line 207, in _trampoline
    mark_as_closed=self._mark_as_closed)
  File "C:\Anaconda2\lib\site-packages\eventlet\hubs\__init__.py", line 163, in trampoline
    return hub.switch()
  File "C:\Anaconda2\lib\site-packages\eventlet\hubs\hub.py", line 295, in switch
    return self.greenlet.switch()
timeout: timed out
question

Most helpful comment

Am I doing anything wrong?

Pretty sure you are, but it's not in the code that you shared. When you use eventlet your tasks need to proactively give up the CPU, so that other tasks can run. My guess is that one of your tasks runs for a long time, without releasing the CPU, so the other tasks, including the one that runs the web server, end up starving.

To release the CPU you can use socketio.sleep(0). This needs to be done routinely in any tasks that are long running.

All 3 comments

Did you monkey patch the Python standard library for eventlet?

I didn't do that. But I just did now eventlet monkey patching in run.py file. Please find the updated code below.

import eventlet
eventlet.monkey_patch()
from app import app
from app.utils.config import server_ip, server_port, is_debug_enabled
from app.celery_app import celery
from app.utils import Logger

from app.celery_app import socketio


def run_service():
    Logger.Infolog('Applog', 'Starting Server...')
    socketio.init_app(app)
    print "Running with", socketio.async_mode
    Logger.Infolog('Applog', "Running with " + socketio.async_mode)
    socketio.run(app, host=server_ip, port=server_port)

if __name__ == '__main__':
    run_service()

Still, the error remains same. Please find the stacktrace below.

Traceback (most recent call last):
  File "D:\Projects\AFA\AFA\WindowsService.py", line 62, in main
    self.server = Process(target = run_service())
  File "D:\Projects\AFA\AFA\run.py", line 27, in run_service
    socketio.run(app, host=server_ip, port=server_port)
  File "C:\Anaconda2\lib\site-packages\flask_socketio\__init__.py", line 495, in run
    run_server()
  File "C:\Anaconda2\lib\site-packages\flask_socketio\__init__.py", line 490, in run_server
    log_output=log_output, **kwargs)
  File "C:\Anaconda2\lib\site-packages\eventlet\wsgi.py", line 896, in server
    client_socket = sock.accept()
  File "C:\Anaconda2\lib\site-packages\eventlet\greenio\base.py", line 224, in accept
    self._trampoline(fd, read=True, timeout=self.gettimeout(), timeout_exc=_timeout_exc)
  File "C:\Anaconda2\lib\site-packages\eventlet\greenio\base.py", line 207, in _trampoline
    mark_as_closed=self._mark_as_closed)
  File "C:\Anaconda2\lib\site-packages\eventlet\hubs\__init__.py", line 163, in trampoline
    return hub.switch()
  File "C:\Anaconda2\lib\site-packages\eventlet\hubs\hub.py", line 295, in switch
    return self.greenlet.switch()
timeout: timed out

Am I doing anything wrong?

Am I doing anything wrong?

Pretty sure you are, but it's not in the code that you shared. When you use eventlet your tasks need to proactively give up the CPU, so that other tasks can run. My guess is that one of your tasks runs for a long time, without releasing the CPU, so the other tasks, including the one that runs the web server, end up starving.

To release the CPU you can use socketio.sleep(0). This needs to be done routinely in any tasks that are long running.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

j2logo picture j2logo  路  3Comments

thehelpfulbees picture thehelpfulbees  路  4Comments

novice79 picture novice79  路  3Comments

huangganggui picture huangganggui  路  3Comments

fbussv picture fbussv  路  4Comments