Running a Django 3 python 3.6 application with uwsgi & nginx is throwing too many of these! I have been spending way too much time trying to figure it out, so any help is welcome.
They are defintely not client disconnections. When looking online I find many uwsgi ini configurations and tried many of them, but to no avail. Most of them are HEAD requests from a country that has no business visiting the site, but there are many normal requests also getting this error. The messages look like this:
Uwsgi log:
Tue Sep 22 08:52:16 2020 - SIGPIPE: writing to a closed pipe/socket/fd (probably the client disconnected) on request / (ip x.xx.xx.xx) !!!
Tue Sep 22 08:52:16 2020 - uwsgi_response_writev_headers_and_body_do(): Broken pipe [core/writer.c line 306] during GET / (x.xx.xx.xx)
OSError: write error
[pid: 9852|app: 0|req: 6262/18763] x.xx.xx.xx () {46 vars in 981 bytes} [Tue Sep 22 08:52:15 2020] GET / => generated 0 bytes in 313 msecs (HTTP/1.1 200) 7 headers in 0 bytes (0 switches on core 0)
Nginx access log:
x.xx.xx.xx - - [22/Sep/2020:08:52:16 +0200] "GET / HTTP/1.1" 499 0 "-" "Mozilla/5.0 (iPhone; CPU iPhone OS 13_7 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.1.2 Mobile/15E148 Safari/604.1"
It is not likely users are trying to escape the site in just these mere 313 msecs. This is the minimalist version currently running of the ini:
[uwsgi]
uid=www-data
gid=www-data
project=mysite
chdir=/home/myuser/releases/mysite-website/web
plugin=python36
wsgi-file=mysite/wsgi.py
daemonize=/home/myuser/logs/uwsgi/mysite-website.log
home=/home/myuser/releases/venv
processes = 1
enable-threads = true
socket=/var/run/uwsgi/app/mysite/socket.sock
pidfile=/var/run/uwsgi/app/mysite/project-masterpid
vacuum = true
touch-reload=/home/myuser/releases/mysite-website/web/mysite/wsgi.py
Nginx:
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
uwsgi_pass unix:///var/run/uwsgi/app/mysite/socket.sock;
include uwsgi_params;
uwsgi_param HTTPS on;
uwsgi_param UWSGI_SCHEME https;
uwsgi_read_timeout 60s;
uwsgi_params:
uwsgi_param QUERY_STRING $query_string;
uwsgi_param REQUEST_METHOD $request_method;
uwsgi_param CONTENT_TYPE $content_type;
uwsgi_param CONTENT_LENGTH $content_length;
uwsgi_param REQUEST_URI $request_uri;
uwsgi_param PATH_INFO $document_uri;
uwsgi_param DOCUMENT_ROOT $document_root;
uwsgi_param SERVER_PROTOCOL $server_protocol;
uwsgi_param REQUEST_SCHEME $scheme;
uwsgi_param HTTPS $https if_not_empty;
uwsgi_param REMOTE_ADDR $remote_addr;
uwsgi_param REMOTE_PORT $remote_port;
uwsgi_param SERVER_PORT $server_port;
uwsgi_param SERVER_NAME $server_name;
In my experience these are legitimate disconnections, where the HTTP client (the browser) closes the connection and Nginx in turn closes the file descriptor uWSGI is writing a response to. See full write-up.
I can reliably replicate the issue by visiting any non-trivial Django page and hammering on the F5 (refresh) key a few times rapidly. That suggests that the errors are part of normal operation and aren't causing any negative user experience, so are likely safe to ignore.
It's certainly possible that these disconnections are caused by are badly behaving HTTP clients or automated attacks, but both of these are outside of your control.
To hide these exceptions in the logs you need all three of the following uWSGI settings, each corresponding to one of the error lines you listed.
ignore-sigpipe
ignore-write-errors
disable-write-exception
The disable-write-errors
option will also prevent the errors being sent to a tool like Sentry if you're using something like that.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With