2

Description: I have a small image server, where you can set an image name 1 and image name 2 from two different devices and the server displays the image path consisting of both names. E.g. Device 1 sets the image 1 to foo and device 2 sets the image 2 to bar then the server will display the image foo_bar.png and reload the browser using redis pub sub mechanism and SSE. Below the code for the image server:

from flask import Flask, render_template, Response
import os
import redis

app = Flask(__name__)
pool = redis.ConnectionPool(host="localhost", port=6379)
red = redis.StrictRedis(connection_pool=pool)


@app.route("/")
@app.route("/get_image")
def get_image():
    image_1_name = app.config['image_1_name']
    image_2_name = app.config['image_2_name']
    image_exists = False
    image_name = "{} {}.png".format(image_1_name, image_2_name)
    if image_1_name != "'-'" and image_2_name != "'-'":
        image_path = os.path.join("static", image_name)
        if os.path.isfile(image_path):
            image_exists = True
    return render_template("image_server.html", image_path=image_name, image_exists=image_exists)


@app.route("/set_image/<sign1>/<sign2>")
def set_image(sign1, sign2):
    image_name = "{} {}.png".format(sign1, sign2)
    app.config['image_name'] = image_name
    red.publish("chat", "Reload")
    return {"success": True}


@app.route("/set_image_n/<n>/<sign>")
def set_image_n(n, sign):
    app.config[f'image_{n}_name'] = sign
    red.publish("chat", "Reload")
    return {"success": True}


def event_stream():
    pubsub = red.pubsub()
    pubsub.subscribe('chat')
    for message in pubsub.listen():
        yield 'data: %s\n\n' % message['data']


@app.route('/stream')
def stream():
    return Response(event_stream(), mimetype="text/event-stream")


if __name__ == '__main__':
    app.config['image_name'] = "'-'"
    app.config['image_1_name'] = "'-'"
    app.config['image_2_name'] = "'-'"
    app.run(host="0.0.0.0", debug=False, use_reloader=False, threaded=True)

and the template:

<!doctype html>
<!--suppress HtmlFormInputWithoutLabel, HtmlFormInputWithoutLabel, HtmlUnknownTarget -->
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Image server</title>
</head>
<body>
    {% if image_exists %}
        <img src="{{ url_for('static', filename=image_path )}}" alt="User Image">
    {% else %}
        The sign combination {{ image_path }} doesn't exist
    {% endif %}
</body>
<style>
    html,body{
    margin:0;
    height:100%;
    }
    img{
      display:block;
      width:100%; height:100%;
      object-fit: cover;
    }
</style>
<script>
    let source = new EventSource('/stream');
    source.onmessage = function (event) {
        if(event.data === "b'Reload'"){
            location.reload();
        }
    };
</script>
</html>

Now I have following small test script running on two different computer and having localhost open on the device running the webservice. One device is n=1 the other n=2:

import time
import requests

counter = 0
url = "192.168.254.181"
while True:
    if counter % 10 == 0:
        print(counter)
    requests.get(f"http://{url}:5000/set_image_n/1/60")
    counter += 1
    time.sleep(1)


Now when letting this loop run for thousands of calls everything works as expected, but after a while, it can be a few hundred calls or a few thousand before the issue happens, I get following stacktrace:


127.0.0.1 - - [10/May/2021 17:09:44] "[37mGET / HTTP/1.1[0m" 200 -
127.0.0.1 - - [10/May/2021 17:09:44] "[36mGET /static/60%2080.png HTTP/1.1[0m" 304 -
127.0.0.1 - - [10/May/2021 17:09:44] "[37mGET /stream HTTP/1.1[0m" 200 -
192.168.254.18 - - [10/May/2021 17:09:45] "[36mGET /static/60%2080.png HTTP/1.1[0m" 304 -
192.168.254.18 - - [10/May/2021 17:09:45] "[37mGET /stream HTTP/1.1[0m" 200 -
192.168.254.13 - - [10/May/2021 17:09:45] "[37mGET /set_image_n/1/60 HTTP/1.1[0m" 200 -
127.0.0.1 - - [10/May/2021 17:09:45] "[37mGET / HTTP/1.1[0m" 200 -
192.168.254.18 - - [10/May/2021 17:09:45] "[37mGET / HTTP/1.1[0m" 200 -
127.0.0.1 - - [10/May/2021 17:09:46] "[36mGET /static/60%2080.png HTTP/1.1[0m" 304 -
127.0.0.1 - - [10/May/2021 17:09:46] "[37mGET /stream HTTP/1.1[0m" 200 -
192.168.254.18 - - [10/May/2021 17:09:46] "[36mGET /static/60%2080.png HTTP/1.1[0m" 304 -
192.168.254.18 - - [10/May/2021 17:09:46] "[37mGET /stream HTTP/1.1[0m" 200 -
192.168.254.27 - - [10/May/2021 17:09:47] "[37mGET /set_image_n/2/60 HTTP/1.1[0m" 200 -
127.0.0.1 - - [10/May/2021 17:09:47] "[37mGET / HTTP/1.1[0m" 200 -
192.168.254.18 - - [10/May/2021 17:09:47] "[37mGET / HTTP/1.1[0m" 200 -
127.0.0.1 - - [10/May/2021 17:09:48] "[36mGET /static/60%2060.png HTTP/1.1[0m" 304 -
127.0.0.1 - - [10/May/2021 17:09:48] "[37mGET /stream HTTP/1.1[0m" 200 -
192.168.254.18 - - [10/May/2021 17:09:48] "[36mGET /static/60%2060.png HTTP/1.1[0m" 304 -
192.168.254.18 - - [10/May/2021 17:09:48] "[37mGET /stream HTTP/1.1[0m" 200 -
[2021-05-10 17:09:48,817] ERROR in app: Exception on /set_image_n/1/60 [GET]
Traceback (most recent call last):
  File "/home/usr/project/lib/python3.9/site-packages/redis/connection.py", line 559, in connect
  File "/home/usr/project/lib/python3.9/site-packages/redis/connection.py", line 584, in _connect
  File "/usr/lib/python3.9/socket.py", line 953, in getaddrinfo
OSError: [Errno 16] Device or resource busy

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/usr/project/lib/python3.9/site-packages/flask/app.py", line 2447, in wsgi_app
  File "/home/usr/project/lib/python3.9/site-packages/flask/app.py", line 1952, in full_dispatch_request
  File "/home/usr/project/lib/python3.9/site-packages/flask/app.py", line 1821, in handle_user_exception
  File "/home/usr/project/lib/python3.9/site-packages/flask/_compat.py", line 39, in reraise
  File "/home/usr/project/lib/python3.9/site-packages/flask/app.py", line 1950, in full_dispatch_request
  File "/home/usr/project/lib/python3.9/site-packages/flask/app.py", line 1936, in dispatch_request
  File "/home/usr/project/src/project/image_server.py", line 35, in set_image_n
  File "/home/usr/project/lib/python3.9/site-packages/redis/client.py", line 3098, in publish
  File "/home/usr/project/lib/python3.9/site-packages/redis/client.py", line 898, in execute_command
  File "/home/usr/project/lib/python3.9/site-packages/redis/connection.py", line 1192, in get_connection
  File "/home/usr/project/lib/python3.9/site-packages/redis/connection.py", line 563, in connect
redis.exceptions.ConnectionError: Error 16 connecting to localhost:6379. Device or resource busy.
192.168.254.13 - - [10/May/2021 17:09:48] "[35m[1mGET /set_image_n/1/60 HTTP/1.1[0m" 500 -
[2021-05-10 17:09:49,815] ERROR in app: Exception on /set_image_n/2/80 [GET]
Traceback (most recent call last):
  File "/home/usr/project/lib/python3.9/site-packages/redis/connection.py", line 559, in connect
  File "/home/usr/project/lib/python3.9/site-packages/redis/connection.py", line 584, in _connect
  File "/usr/lib/python3.9/socket.py", line 953, in getaddrinfo
OSError: [Errno 16] Device or resource busy

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/usr/project/lib/python3.9/site-packages/flask/app.py", line 2447, in wsgi_app
  File "/home/usr/project/lib/python3.9/site-packages/flask/app.py", line 1952, in full_dispatch_request
  File "/home/usr/project/lib/python3.9/site-packages/flask/app.py", line 1821, in handle_user_exception
  File "/home/usr/project/lib/python3.9/site-packages/flask/_compat.py", line 39, in reraise
  File "/home/usr/project/lib/python3.9/site-packages/flask/app.py", line 1950, in full_dispatch_request
  File "/home/usr/project/lib/python3.9/site-packages/flask/app.py", line 1936, in dispatch_request
  File "/home/usr/project/src/project/image_server.py", line 35, in set_image_n
  File "/home/usr/project/lib/python3.9/site-packages/redis/client.py", line 3098, in publish
  File "/home/usr/project/lib/python3.9/site-packages/redis/client.py", line 898, in execute_command
  File "/home/usr/project/lib/python3.9/site-packages/redis/connection.py", line 1192, in get_connection
  File "/home/usr/project/lib/python3.9/site-packages/redis/connection.py", line 563, in connect
redis.exceptions.ConnectionError: Error 16 connecting to localhost:6379. Device or resource busy.

My question would be what resource or device is busy? The redis-server or the port? How come it can run for thousand of calls but then once it is busy it stays busy forever? My main issue is that it doesn't recover itself, it would be fine to be busy some calls, but after it is busy once it stays busy forever.

Version: redis: 6.0.11 redis-py: 3.5.3

Platform: What platform / version? (For example Python 3.5.1 on Windows 7 / Ubuntu 15.10 / Azure) Ubuntu 21.04 on a raspberry pi 4B running Python 3.9.4 ulimit: unlimited cat /proc/sys/fs/inotify/max_user_watches 65536

Hakaishin
  • 2,550
  • 3
  • 27
  • 45

0 Answers0