avocado/core/main.py
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; specifically version 2 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#
# See LICENSE for more details.
#
# Copyright: RedHat 2013-2014
# Author: Lucas Meneghel Rodrigues <lmr@redhat.com>
import multiprocessing
import os
import sys
import tempfile
import time
import traceback
try:
from avocado.core import exit_codes
from avocado.core.settings import settings
except ImportError:
sys.stderr.write(
"Unable to import Avocado libraries, please verify "
"your installation, and if necessary reinstall it.\n"
)
# This exit code is replicated from avocado/core/exit_codes.py and not
# imported because we are dealing with import failures
sys.exit(-1)
def get_crash_dir():
config = settings.as_dict()
crash_dir_path = os.path.join(config.get("datadir.paths.data_dir"), "crashes")
try:
os.makedirs(crash_dir_path)
except OSError:
pass
return crash_dir_path
def handle_exception(*exc_info):
tb = "".join(traceback.format_exception(*exc_info))
# Store traceback in data_dir or TMPDIR
prefix = "avocado-traceback-"
prefix += time.strftime("%F_%T") + "-"
tmp, name = tempfile.mkstemp(".log", prefix, get_crash_dir())
os.write(tmp, tb.encode("utf-8"))
os.close(tmp)
if exc_info[0] is KeyboardInterrupt:
os.write(
2,
f"{exc_info[0].__doc__}\nYou can find details in {name}\n".encode("utf-8"),
)
exit_code = exit_codes.AVOCADO_JOB_INTERRUPTED
else:
# Print friendly message and traceback in console-like output
os.write(2, f"Avocado crashed unexpectedly: {exc_info[1]}\n".encode("utf-8"))
os.write(2, tb.encode("utf-8"))
os.write(2, f"\nYou can also find details in {name}\n".encode("utf-8"))
exit_code = exit_codes.AVOCADO_GENERIC_CRASH
sys.exit(exit_code)
def main():
if sys.platform == "darwin":
multiprocessing.set_start_method("fork")
sys.excepthook = handle_exception
from avocado.core.app import AvocadoApp # pylint: disable=E0611
# Override tmp in case it's not set in env
for attr in ("TMP", "TEMP", "TMPDIR"):
if attr in os.environ:
break
else: # TMP not set by user, use /var/tmp if exists
# TMP not set by user in environment. Try to use /var/tmp to avoid
# possible problems with "/tmp" being mounted as TMPFS without the
# support for O_DIRECT
if os.path.exists("/var/tmp"):
os.environ["TMP"] = "/var/tmp"
app = AvocadoApp()
return app.run()
if __name__ == "__main__":
sys.exit(main())