Beispiel #1
0
    def run(self, task: Any = None, cwd: str = ".") -> None:
        """Actually run the test.

        Calls Popen with the command to fork a new process.
        Then, this function polls the process every 5 seconds to check if it
        has finished or not. Each time it checks, it dumps the json info so
        other applications can poll those files.

        task is the celery task that is running this gem5 instance.

        cwd is the directory to change to before running. This allows a server
        process to run in a different directory than the running process. Note
        that only the spawned process runs in the new directory.
        """
        # Check if the run is already in the database
        db = artifact.getDBConnection()
        if self.hash in db:
            print(f"Error: Have already run {self.command}. Exiting!")
            return
        self._run(task, cwd)
Beispiel #2
0
    def run(self, task: Any = None, cwd: str = '.') -> None:
        """Actually run the test.

        Calls Popen with the command to fork a new process.
        Then, this function polls the process every 5 seconds to check if it
        has finished or not. Each time it checks, it dumps the json info so
        other applications can poll those files.

        task is the celery task that is running this gem5 instance.

        cwd is the directory to change to before running. This allows a server
        process to run in a different directory than the running process. Note
        that only the spawned process runs in the new directory.
        """
        # Check if the run is already in the database
        db = artifact.getDBConnection()
        if self.hash in db:
            print(f"Error: Have already run {self.command}. Exiting!")
            return

        self.status = "Begin run"
        self.dumpJson('info.json')

        if not self.checkArtifacts(cwd):
            self.dumpJson('info.json')
            return

        self.status = "Spawning"

        self.start_time = time.time()
        self.task_id = task.request.id if task else None
        self.dumpJson('info.json')

        # Start running the gem5 command
        proc = subprocess.Popen(self.command, cwd=cwd)

        # Register handler in case this process is killed while the gem5
        # instance is running. Note: there's a bit of a race condition here,
        # but hopefully it's not a big deal
        def handler(signum, frame):
            proc.kill()
            self.kill_reason = 'sigterm'
            self.dumpJson('info.json')
            # Note: We'll fall out of the while loop after this.

        # This makes it so if you term *this* process, it will actually kill
        # the subprocess and then this process will die.
        signal.signal(signal.SIGTERM, handler)

        # Do this until the subprocess is done (successfully or not)
        while proc.poll() is None:
            self.status = "Running"
            # Still running
            self.current_time = time.time()
            self.pid = proc.pid
            self.running = True

            if self.current_time - self.start_time > self.timeout:
                proc.kill()
                self.kill_reason = 'timeout'

            if self.checkKernelPanic():
                proc.kill()
                self.kill_reason = 'kernel panic'

            self.dumpJson('info.json')

            # Check again in five seconds
            time.sleep(5)

        print("Done running {}".format(' '.join(self.command)))

        # Done executing
        self.running = False
        self.end_time = time.time()
        self.return_code = proc.returncode

        if self.return_code == 0:
            self.status = "Finished"
        else:
            self.status = "Failed"

        self.dumpJson('info.json')

        self.saveResults()

        # Store current gem5 run in the database
        db.put(self._id, self._getSerializable())

        print("Done storing the results of {}".format(' '.join(self.command)))
Beispiel #3
0
import hashlib
import json
import os
from pathlib import Path
import signal
import subprocess
import time
from typing import Any, Dict, Iterable, List, Optional, Tuple, Union
from uuid import UUID, uuid4
import zipfile

from gem5art import artifact
from gem5art.artifact import Artifact

_db: artifact._artifactdb.ArtifactDB = artifact.getDBConnection()

class gem5Run:
    """
    This class holds all of the info required to run gem5.
    """

    _id: UUID
    hash: str
    type: str
    name: str
    gem5_binary: Path
    run_script: Path
    gem5_artifact: Artifact
    gem5_git_artifact: Artifact
    run_script_git_artifact: Artifact
Beispiel #4
0
    def _run(self, task: Any = None, cwd: str = ".") -> None:
        """Actually run the test.

        Calls Popen with the command to fork a new process.
        Then, this function polls the process every 5 seconds to check if it
        has finished or not. Each time it checks, it dumps the json info so
        other applications can poll those files.

        task is the celery task that is running this gem5 instance.

        cwd is the directory to change to before running. This allows a server
        process to run in a different directory than the running process. Note
        that only the spawned process runs in the new directory.
        """
        # Connect to the database
        db = artifact.getDBConnection()

        self.status = "Begin run"
        self.dumpJson("info.json")

        if not self.checkArtifacts(cwd):
            self.dumpJson("info.json")
            return

        self.status = "Spawning"

        self.start_time = time.time()
        self.task_id = task.request.id if task else None
        self.dumpJson("info.json")

        # Start running the gem5 command
        proc = subprocess.Popen(self.command, cwd=cwd)

        # Register handler in case this process is killed while the gem5
        # instance is running. Note: there's a bit of a race condition here,
        # but hopefully it's not a big deal
        def handler(signum, frame):
            proc.kill()
            self.kill_reason = "sigterm"
            self.dumpJson("info.json")
            # Note: We'll fall out of the while loop after this.

        # This makes it so if you term *this* process, it will actually kill
        # the subprocess and then this process will die.
        signal.signal(signal.SIGTERM, handler)

        # Do this until the subprocess is done (successfully or not)
        while proc.poll() is None:
            self.status = "Running"
            # Still running
            self.current_time = time.time()
            self.pid = proc.pid
            self.running = True

            if self.current_time - self.start_time > self.timeout:
                proc.kill()
                self.kill_reason = "timeout"

            if self.checkKernelPanic():
                proc.kill()
                self.kill_reason = "kernel panic"

            # Assigning a function/lambda to an object variable does not make
            # the function/lambda become a bound one. Therefore, the
            # user-defined function must pass `self` in.
            # Here, mypy classifies self.check_failure() as a bound function,
            # so we tell mypy to ignore it./
            if self.check_failure(self):  # type: ignore
                proc.kill()
                self.kill_reason = "User defined kill"

            self.dumpJson("info.json")

            # Check again in five seconds
            time.sleep(5)

        print("Done running {}".format(" ".join(self.command)))

        # Done executing
        self.running = False
        self.end_time = time.time()
        self.return_code = proc.returncode

        if self.return_code == 0:
            self.status = "Finished"
        else:
            self.status = "Failed"

        self.dumpJson("info.json")

        self.saveResults()

        # Store current gem5 run in the database
        db.put(self._id, self._getSerializable())

        print("Done storing the results of {}".format(" ".join(self.command)))