Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 42 additions & 11 deletions vpython/no_notebook.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,14 @@
import copy
import socket
import multiprocessing

import time

import signal
from urllib.parse import unquote

from .rate_control import rate

makeDaemonic = (platform.system() == "Windows")

# Redefine `Thread.run` to not show a traceback for Spyder when stopping
# the server by raising a KeyboardInterrupt or SystemExit.
Expand All @@ -38,7 +39,8 @@ def run(*args, **kwargs):
try:
run_old(*args, **kwargs)
except (KeyboardInterrupt, SystemExit):
print("VPython server stopped.")
pass
# ("VPython server stopped.")
except:
raise
threading.Thread.run = run
Expand All @@ -49,9 +51,9 @@ def run(*args, **kwargs):

# Check for Ctrl+C. SIGINT will also be sent by our code if WServer is closed.
def signal_handler(signal, frame):
#print("in signal handler, calling stop server")
stop_server()


signal.signal(signal.SIGINT, signal_handler)

# Requests from client to http server can be the following:
Expand Down Expand Up @@ -211,8 +213,18 @@ async def onMessage(self, data, isBinary):
# message format used by notebook
msg = {'content': {'data': [m]}}
loop = asyncio.get_event_loop()
await loop.run_in_executor(None, GW.handle_msg, msg)

try:
await loop.run_in_executor(None, GW.handle_msg, msg)
except:
#
# this will throw a runtime exception after the main Thread
# has stopped, but we don't really case since the main thread
# is no longer there to do anything anyway.
if threading.main_thread().is_alive():
raise
else:
pass

def onClose(self, wasClean, code, reason):
"""Called when browser tab is closed."""
global websocketserving
Expand Down Expand Up @@ -293,7 +305,7 @@ def start_Qapp(port):
__m = multiprocessing.Process(target=start_Qapp, args=(__HTTP_PORT,))
__m.start()

__w = threading.Thread(target=__server.serve_forever)
__w = threading.Thread(target=__server.serve_forever, daemon=makeDaemonic)
__w.start()


Expand Down Expand Up @@ -326,14 +338,16 @@ def start_websocket_server():
# Put the websocket server in a separate thread running its own event loop.
# That works even if some other program (e.g. spyder) already running an
# async event loop.
__t = threading.Thread(target=start_websocket_server)
__t = threading.Thread(target=start_websocket_server, daemon=makeDaemonic)
__t.start()


def stop_server():
"""Shuts down all threads and exits cleanly."""
#print("in stop server")
global __server
__server.shutdown()

event_loop = txaio.config.loop
event_loop.stop()
# We've told the event loop to stop, but it won't shut down until we poke
Expand All @@ -352,19 +366,36 @@ def stop_server():
raise KeyboardInterrupt

if threading.main_thread().is_alive():
#print("main is alive...")
sys.exit(0)
else:
pass
#
# check to see if the event loop is still going, if so join it.
#
#print("main is dead..")
if __t.is_alive():
#print("__t is alive still")
if threading.get_ident() != __t.ident:
#print("but it's not my thread, so I'll join...")
__t.join()
else:
#print("__t is alive, but that's my thread! So skip it.")
pass
else:
if makeDaemonic:
sys.exit(0)

# If the main thread has already stopped, the python interpreter
# is likely just running .join on the two remaining threads (in
# python/threading.py:_shutdown). Since we just stopped those threads,
# we'll now exit.



GW = GlowWidget()

while not (httpserving and websocketserving): # try to make sure setup is complete
rate(60)
time.sleep(0.1)


# Dummy variable to import
_ = None

11 changes: 7 additions & 4 deletions vpython/vpython.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,17 @@
from ._notebook_helpers import _isnotebook
from ._vector_import_helper import (vector, mag, norm, cross, dot, adjust_up,
adjust_axis, object_rotate)


def Exit():
zero = 0.
print('exit')
a = 1.0/zero
# no infinite loop here so build processs can finish.
# print("in atexit")
pass

import atexit
atexit.register(Exit)

if platform.system() == 'Windows':
atexit.register(Exit)

# List of names that will be imported from this file with import *
__all__ = ['Camera', 'GlowWidget', 'version', 'GSversion', 'Mouse', 'arrow', 'attach_arrow',
Expand Down
2 changes: 1 addition & 1 deletion vpython/vpython_libraries/glow.min.js

Large diffs are not rendered by default.