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:
resp = urllib.request.urlopen( app.url_for("ping") ).read()
assert resp == b"pong"
assert resp.startswith( b"pong: " )
return True
except URLError:
return False

@ -5,9 +5,11 @@ import sys
import os
import os.path
import threading
import time
import traceback
import logging
import urllib.request
from urllib.error import URLError
import PyQt5.QtWebEngineWidgets
from PyQt5.QtWidgets import QApplication, QMessageBox
@ -22,6 +24,8 @@ qt_app = QApplication( sys.argv )
app_settings = None
_webapp_error = None # nb: this needs to be global :shrug:
# ---------------------------------------------------------------------
_QT_LOGGING_LEVELS = {
@ -127,28 +131,57 @@ def _do_main( template_pack, default_scenario, remote_debugging, debug ): #pylin
import flask.cli
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
port = webapp.config[ "FLASK_PORT_NO" ]
def webapp_thread():
"""Run the webapp server."""
try:
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( 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 )
# 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()
# 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
# 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:

@ -2,6 +2,7 @@
import os
import json
import uuid
import logging
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 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
_check_versions = True
@ -159,7 +163,7 @@ def get_default_scenario():
@app.route( "/ping" )
def ping():
"""Let the caller know we're alive."""
return "pong"
return "pong: {}".format( INSTANCE_ID )
# ---------------------------------------------------------------------

Loading…
Cancel
Save