mirror of
https://github.com/bugsink/bugsink.git
synced 2026-01-07 05:40:26 -06:00
Remove cornless servers
https://www.bugsink.com/blog/disposable-web-servers/ is where they live now
This commit is contained in:
@@ -1,54 +0,0 @@
|
||||
# A super-simple utility to run the WSGI application using the built-in WSGI server. The usefulness of this script is
|
||||
# precisely because there is _no_ special handling of SIGINT. This means that SIGINT can be used to get a traceback
|
||||
# from the application as it was when interrupted. This is useful to answer the question "why is this application
|
||||
# stuck?"
|
||||
|
||||
# This version is for SQLite. sqlite3 does not support interrupts (i.e. it does not check with Python's signal handler),
|
||||
# so we need to do it ourselves. This is done by calling the `interrupt()` method on the default connection.
|
||||
|
||||
# Because SQLite does not support interrupts, we need to spin up a new thread to run the server, so that the main thread
|
||||
# can be interrupted with SIGINT. We then call the `interrupt()` method on the default connection to interrupt the
|
||||
# query. (We have observed that the standard sentry sdk does not play well with this threaded server; when sentry is not
|
||||
# used you get a nice 500 page and the server serves the next request; when it is used, the server somehow hangs. I did
|
||||
# not investigate further, will instead create a simplified version of the sentry client for such cases.)
|
||||
|
||||
import sys
|
||||
import signal
|
||||
import threading
|
||||
|
||||
from wsgiref import simple_server
|
||||
from bugsink.wsgi import application
|
||||
from django.db import connections
|
||||
|
||||
|
||||
class ImpureObject(object):
|
||||
"""'impure' object in the sense that it is not purely 'object()', i.e. it allows setting attributes"""
|
||||
|
||||
|
||||
def handle_sigint(signum, frame):
|
||||
connections["default"].connection.interrupt()
|
||||
sys.exit()
|
||||
|
||||
|
||||
def server():
|
||||
if len(sys.argv) < 2:
|
||||
host = "127.0.0.1"
|
||||
port = 8000
|
||||
else:
|
||||
host = sys.argv[1].split(":")[0]
|
||||
port = int(sys.argv[1].split(":")[1])
|
||||
|
||||
httpd = simple_server.make_server(host, port, application)
|
||||
httpd.serve_forever()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# we override connections._connections to get rid of the thread-local behavior; this is necessary to be able to
|
||||
# interrupt the connection from the main thread (I wouldn't know how to do it otherwise)
|
||||
connections._connections = ImpureObject()
|
||||
|
||||
signal.signal(signal.SIGINT, handle_sigint)
|
||||
|
||||
t = threading.Thread(target=server)
|
||||
t.start()
|
||||
t.join()
|
||||
@@ -1,54 +0,0 @@
|
||||
# A super-simple utility to run the WSGI application using the built-in WSGI server. The usefulness of this script is
|
||||
# precisely because there is _no_ special handling of SIGINT. This means that SIGINT can be used to get a traceback
|
||||
# from the application as it was when interrupted. This is useful to answer the question "why is this application
|
||||
# stuck?"
|
||||
|
||||
# This version spins up a new thread to run the server, so that the main thread can be interrupted with SIGINT. This is
|
||||
# useful when Python's signal-handling is not working, e.g. when running a long-running piece of C code that does not
|
||||
# regularly do the call to the Python signal check. See cornless-interrupt-sqlite.py for a warning about sentry_sdk
|
||||
# (observed there, but may apply here too)
|
||||
|
||||
# Ideas from:
|
||||
# https://stackoverflow.com/questions/1032813/dump-stacktraces-of-all-active-threads
|
||||
|
||||
# https://stackoverflow.com/a/43242295/339144 (the idea to use a separate thread for the server comes from here, and it
|
||||
# contains ideas on sqlite3 more generally)
|
||||
|
||||
import sys
|
||||
import signal
|
||||
import traceback
|
||||
import threading
|
||||
# import faulthandler
|
||||
|
||||
|
||||
from wsgiref import simple_server
|
||||
from bugsink.wsgi import application
|
||||
|
||||
|
||||
def handle_sigint(signum, frame):
|
||||
print("Caught SIGINT")
|
||||
# alternatively, a more robust (but uglier) version:
|
||||
# faulthandler.dump_traceback(all_threads=True)
|
||||
|
||||
traceback.print_stack(sys._current_frames()[server_thread.ident])
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def server():
|
||||
if len(sys.argv) < 2:
|
||||
host = "127.0.0.1"
|
||||
port = 8000
|
||||
else:
|
||||
host = sys.argv[1].split(":")[0]
|
||||
port = int(sys.argv[1].split(":")[1])
|
||||
|
||||
httpd = simple_server.make_server(host, port, application)
|
||||
httpd.serve_forever()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
signal.signal(signal.SIGINT, handle_sigint)
|
||||
|
||||
server_thread = threading.Thread(target=server)
|
||||
server_thread.start()
|
||||
server_thread.join()
|
||||
@@ -1,66 +0,0 @@
|
||||
# A super-simple utility to run the WSGI application using the built-in WSGI server. The usefulness of this script is
|
||||
# precisely because there is _no_ special handling of SIGINT. This means that SIGINT can be used to get a traceback
|
||||
# from the application as it was when interrupted. This is useful to answer the question "why is this application
|
||||
# stuck?"
|
||||
|
||||
# This version is for SQLite. sqlite3 does not support interrupts (i.e. it does not check with Python's signal handler),
|
||||
# so we need to do it ourselves. In this case we attempt that by setting a progress handler that checks for a global
|
||||
# variable that is set by the signal handler.
|
||||
|
||||
# This solution prints a stack trace, but then hangs for reasons I don't understand.
|
||||
# (a version without a signal handler (implicit KeyboardInterrupt) works just as well / just as poorly)
|
||||
|
||||
import sys
|
||||
import signal
|
||||
|
||||
from wsgiref import simple_server
|
||||
from bugsink.wsgi import application
|
||||
from django.db.backends.sqlite3.base import DatabaseWrapper
|
||||
|
||||
|
||||
interrupted = False
|
||||
|
||||
|
||||
def handle_sigint(signal, frame):
|
||||
global interrupted
|
||||
interrupted = True
|
||||
|
||||
|
||||
signal.signal(signal.SIGINT, handle_sigint)
|
||||
|
||||
|
||||
def stop_when_interrupted():
|
||||
global interrupted
|
||||
if interrupted:
|
||||
interrupted = False
|
||||
return -1
|
||||
return 0
|
||||
|
||||
|
||||
def get_new_connection_with_check(self, conn_params):
|
||||
conn = original_get_new_connection(self, conn_params)
|
||||
# this is the first thing I tried; it works just fine, but so does any old python code, because any old python code
|
||||
# has PyErr_CheckSignals in its execution path.
|
||||
# conn.set_progress_handler(ctypes.pythonapi.PyErr_CheckSignals, 50)
|
||||
conn.set_progress_handler(stop_when_interrupted, 50)
|
||||
# conn.set_progress_handler(lambda: None, 50) # the version without the signal handler (assumes signal.siganl is
|
||||
# not done, and the lambda is a moment for the regular Python signal handler, which raises keyboardInterrupt, to
|
||||
# run)
|
||||
return conn
|
||||
|
||||
|
||||
original_get_new_connection = DatabaseWrapper.get_new_connection
|
||||
DatabaseWrapper.get_new_connection = get_new_connection_with_check
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
# the actual server:
|
||||
if len(sys.argv) < 2:
|
||||
host = "127.0.0.1"
|
||||
port = 8000
|
||||
else:
|
||||
host = sys.argv[1].split(":")[0]
|
||||
port = int(sys.argv[1].split(":")[1])
|
||||
|
||||
httpd = simple_server.make_server(host, port, application)
|
||||
httpd.serve_forever()
|
||||
21
cornless.py
21
cornless.py
@@ -1,21 +0,0 @@
|
||||
# A super-simple utility to run the WSGI application using the built-in WSGI server. The usefulness of this script is
|
||||
# precisely because there is _no_ special handling of SIGINT. This means that SIGINT can be used to get a traceback
|
||||
# from the application as it was when interrupted. This is useful to answer the question "why is this application
|
||||
# stuck?"
|
||||
|
||||
import sys
|
||||
|
||||
from wsgiref import simple_server
|
||||
from bugsink.wsgi import application
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) < 2:
|
||||
host = "127.0.0.1"
|
||||
port = 8000
|
||||
else:
|
||||
host = sys.argv[1].split(":")[0]
|
||||
port = int(sys.argv[1].split(":")[1])
|
||||
|
||||
httpd = simple_server.make_server("", port, application)
|
||||
httpd.serve_forever()
|
||||
Reference in New Issue
Block a user