Changed how we detect if the program is already running.

master
Pacman Ghost 4 years ago
parent a5bd1b8b7e
commit 7afae4fd8d
  1. 2
      conftest.py
  2. 57
      vasl_templates/main.py
  3. 6
      vasl_templates/webapp/main.py

@ -132,7 +132,7 @@ def webapp():
"""Try to connect to the webapp server.""" """Try to connect to the webapp server."""
try: try:
resp = urllib.request.urlopen( app.url_for("ping") ).read() resp = urllib.request.urlopen( app.url_for("ping") ).read()
assert resp == b"pong" assert resp.startswith( b"pong: " )
return True return True
except URLError: except URLError:
return False return False

@ -5,9 +5,11 @@ import sys
import os import os
import os.path import os.path
import threading import threading
import time
import traceback import traceback
import logging import logging
import urllib.request import urllib.request
from urllib.error import URLError
import PyQt5.QtWebEngineWidgets import PyQt5.QtWebEngineWidgets
from PyQt5.QtWidgets import QApplication, QMessageBox from PyQt5.QtWidgets import QApplication, QMessageBox
@ -22,6 +24,8 @@ qt_app = QApplication( sys.argv )
app_settings = None app_settings = None
_webapp_error = None # nb: this needs to be global :shrug:
# --------------------------------------------------------------------- # ---------------------------------------------------------------------
_QT_LOGGING_LEVELS = { _QT_LOGGING_LEVELS = {
@ -127,28 +131,57 @@ def _do_main( template_pack, default_scenario, remote_debugging, debug ): #pylin
import flask.cli import flask.cli
flask.cli.show_server_banner = lambda *args: None flask.cli.show_server_banner = lambda *args: None
# see if we can connect to the webapp server
port = webapp.config["FLASK_PORT_NO"]
url = "http://localhost:{}/ping".format( port )
try:
resp = urllib.request.urlopen( url ).read()
except: #pylint: disable=bare-except
resp = None
if resp:
raise SimpleError( "The application is already running." )
# start the webapp server # start the webapp server
port = webapp.config[ "FLASK_PORT_NO" ]
def webapp_thread(): def webapp_thread():
"""Run the webapp server.""" """Run the webapp server."""
try: try:
webapp.run( host="localhost", port=port, use_reloader=False ) webapp.run( host="localhost", port=port, use_reloader=False )
except Exception as ex: except Exception as ex: #pylint: disable=broad-except
logging.critical( "WEBAPP SERVER EXCEPTION: %s", ex ) logging.critical( "WEBAPP SERVER EXCEPTION: %s", ex )
logging.critical( traceback.format_exc() ) logging.critical( traceback.format_exc() )
raise # NOTE: We pass the exception to the GUI thread, where it can be shown to the user.
global _webapp_error
_webapp_error = ex
thread = threading.Thread( target=webapp_thread ) thread = threading.Thread( target=webapp_thread )
# FUDGE! If we detect another instance, we hang on Windows after reporting the error. Running the webapp
# in a daemon thread makes the problem go away - you would think the thread would terminate, since it wouldn't
# be able to listen on the same server port - but I guess not :-/
thread.daemon = True
thread.start() thread.start()
# NOTE: We want to detect if another instance of the program is already running, but we can't simply
# try to connect to the webapp, since we can't tell the difference between connecting to the webapp
# we just started above, and an already-running instance. We handle this by assigning each instance
# a unique ID, which lets us figure out if we've connected to ourself, or another instance.
from vasl_templates.webapp.main import INSTANCE_ID
# wait for the webapp server to start
while True:
if _webapp_error:
break
try:
url = "http://localhost:{}/ping".format( port )
resp = urllib.request.urlopen( url ).read().decode( "utf-8" )
# we got a response - figure out if we connected to ourself or another instance
if resp[:6] != "pong: ":
raise SimpleError( "Unexpected server check response: {}".format( resp ) )
if resp[6:] == INSTANCE_ID:
break
else:
from vasl_templates.webapp.config.constants import APP_NAME
QMessageBox.warning( None, APP_NAME, "The program is already running." )
return -1
except URLError:
# no response - the webapp server is probably still starting up
time.sleep( 0.25 )
continue
except Exception as ex: #pylint: disable=broad-except
raise ex
if _webapp_error:
# the webapp server didn't start up - re-raise the error in this thread
raise _webapp_error #pylint: disable=raising-bad-type
# check if we should disable OpenGL # check if we should disable OpenGL
# Using the QWebEngineView crashes on Windows 7 in a VM. It uses OpenGL, which is # Using the QWebEngineView crashes on Windows 7 in a VM. It uses OpenGL, which is
# apparently not well supported on Windows, and is dependent on the graphics card driver: # apparently not well supported on Windows, and is dependent on the graphics card driver:

@ -2,6 +2,7 @@
import os import os
import json import json
import uuid
import logging import logging
from flask import request, render_template, jsonify, send_file, redirect, url_for, abort from flask import request, render_template, jsonify, send_file, redirect, url_for, abort
@ -12,6 +13,9 @@ import vasl_templates.webapp.config.constants
from vasl_templates.webapp.config.constants import BASE_DIR, DATA_DIR from vasl_templates.webapp.config.constants import BASE_DIR, DATA_DIR
from vasl_templates.webapp import globvars from vasl_templates.webapp import globvars
# NOTE: This is used to stop multiple instances of the program from running (see main.py in the desktop app).
INSTANCE_ID = uuid.uuid4().hex
startup_msg_store = MsgStore() # store messages generated during startup startup_msg_store = MsgStore() # store messages generated during startup
_check_versions = True _check_versions = True
@ -159,7 +163,7 @@ def get_default_scenario():
@app.route( "/ping" ) @app.route( "/ping" )
def ping(): def ping():
"""Let the caller know we're alive.""" """Let the caller know we're alive."""
return "pong" return "pong: {}".format( INSTANCE_ID )
# --------------------------------------------------------------------- # ---------------------------------------------------------------------

Loading…
Cancel
Save