Graceful shutdown for modules and locale check for the server.

This commit is contained in:
grossmj 2014-04-24 15:59:34 -06:00
parent 9be5625c38
commit 7ebd451dda
4 changed files with 52 additions and 6 deletions

View File

@ -20,10 +20,14 @@ import os
import datetime
import sys
import multiprocessing
import locale
import tornado.options
from gns3server.server import Server
from gns3server.version import __version__
import logging
log = logging.getLogger(__name__)
# command line options
from tornado.options import define
define("host", default="0.0.0.0", help="run on the given host/IP address", type=str)
@ -31,13 +35,48 @@ define("port", default=8000, help="run on the given port", type=int)
define("ipc", default=False, help="use IPC for module communication", type=bool)
def locale_check():
"""
Checks if this application runs with a correct locale (i.e. supports UTF-8 encoding) and attempt to fix
if this is not the case.
This is to prevent UnicodeEncodeError with unicode paths when using standard library I/O operation
methods (e.g. os.stat() or os.path.*) which rely on the system or user locale.
"""
# no need to check on Windows
if sys.platform.startswith("win"):
return
language = encoding = None
try:
language, encoding = locale.getlocale()
except ValueError as e:
log.error("could not determine the current locale: {}".format(e))
if not language and not encoding:
try:
log.warn("could not find a default locale, switching to C.UTF-8...")
locale.setlocale(locale.LC_ALL, ("C", "UTF-8"))
except locale.Error as e:
log.error("could not switch to the C.UTF-8 locale: {}".format(e))
raise SystemExit
elif encoding != "UTF-8":
log.warn("your locale {}.{} encoding is not UTF-8, switching to the UTF-8 version...".format(language, encoding))
try:
locale.setlocale(locale.LC_ALL, (language, "UTF-8"))
except locale.Error as e:
log.error("could not set an UTF-8 encoding for the {} locale: {}".format(language, e))
else:
log.info("current locale is {}.{}".format(language, encoding))
def main():
"""
Entry point for GNS3 server
"""
if sys.platform.startswith("win"):
# necessary on Windows to use freezing software
# necessary on Windows to freeze the application
multiprocessing.freeze_support()
current_year = datetime.date.today().year
@ -59,6 +98,8 @@ def main():
tornado.options.print_help()
raise SystemExit
locale_check()
from tornado.options import options
server = Server(options.host,
options.port,

View File

@ -54,6 +54,7 @@ class IModule(multiprocessing.Process):
self._current_session = None
self._current_destination = None
self._current_call_id = None
self._stopping = False
def _setup(self):
"""
@ -128,13 +129,16 @@ class IModule(multiprocessing.Process):
except KeyboardInterrupt:
return
log.info("{} module has stopped".format(self.name))
def stop(self):
"""
Stops the event loop.
"""
if self._ioloop:
self._ioloop.stop()
if not self._stopping:
self._stopping = True
self._ioloop.add_callback_from_signal(self._ioloop.stop)
def send_response(self, results):
"""

View File

@ -442,8 +442,8 @@ class IOUDevice(object):
self._started = True
except OSError as e:
iou_stdout = self.read_iou_stdout()
log.error("could not start IOU: {}\n{}".format(e, iou_stdout))
raise IOUError("could not start IOU: {}\n{}".format(e, iou_stdout))
log.error("could not start IOU {}: {}\n{}".format(self._path, e, iou_stdout))
raise IOUError("could not start IOU {}: {}\n{}".format(self._path, e, iou_stdout))
# start console support
self._start_ioucon()

View File

@ -224,7 +224,8 @@ class Server(object):
# terminate all modules
for module in self._modules:
#module.join(timeout=1)
# if not sys.platform.startswith("win"):
# module.join(timeout=0.5)
if module.is_alive():
log.info("terminating {}".format(module.name))
module.terminate()