avocado-framework/avocado

View on GitHub
avocado/core/main.py

Summary

Maintainability
A
35 mins
Test Coverage
F
41%
# 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())