autograder_sandbox/autograder_sandbox.py
def run_command(self,
                    args: List[str],
                    max_num_processes: int=None,
                    max_stack_size: int=None,
                    max_virtual_memory: int=None,
                    as_root: bool=False,
                    stdin: FileIO=None,
                    timeout: int=None,
                    check: bool=False,
                    truncate_stdout: int=None,
                    truncate_stderr: int=None) -> 'CompletedCommand':
        """
        Runs a command inside the sandbox and returns the results.

        :param args: A list of strings that specify which command should
            be run inside the sandbox.

        :param max_num_processes: The maximum number of processes the
            command is allowed to spawn.

        :param max_stack_size: The maximum stack size, in bytes, allowed
            for the command.

        :param max_virtual_memory: The maximum amount of memory, in
            bytes, allowed for the command.

        :param as_root: Whether to run the command as a root user.

        :param stdin: A file object to be redirected as input to the
            command's stdin. If this is None, /dev/null is sent to the
            command's stdin.

        :param timeout: The time limit for the command.

        :param check: Causes CalledProcessError to be raised if the
            command exits nonzero or times out.

        :param truncate_stdout: When not None, stdout from the command
            will be truncated after this many bytes.

        :param truncate_stderr: When not None, stderr from the command
            will be truncated after this many bytes.
        """
        cmd = ['docker', 'exec', '-i', self.name, 'cmd_runner.py']

        if stdin is None:
            cmd.append('--stdin_devnull')

        if max_num_processes is not None:
            cmd += ['--max_num_processes', str(max_num_processes)]

        if max_stack_size is not None:
            cmd += ['--max_stack_size', str(max_stack_size)]

        if max_virtual_memory is not None:
            cmd += ['--max_virtual_memory', str(max_virtual_memory)]

        if timeout is not None:
            cmd += ['--timeout', str(timeout)]

        if truncate_stdout is not None:
            cmd += ['--truncate_stdout', str(truncate_stdout)]

        if truncate_stderr is not None:
            cmd += ['--truncate_stderr', str(truncate_stderr)]

        if not as_root:
            cmd += ['--linux_user_id', str(self._linux_uid)]

        cmd += args

        if self.debug:
            print('running: {}'.format(cmd), flush=True)

        with tempfile.TemporaryFile() as f:
            try:
                subprocess.run(cmd, stdin=stdin, stdout=f, stderr=subprocess.PIPE, check=True)
                f.seek(0)
                json_len = int(f.readline().decode().rstrip())
                results_json = json.loads(f.read(json_len).decode())

                stdout_len = int(f.readline().decode().rstrip())
                stdout = tempfile.NamedTemporaryFile()
                stdout.write(f.read(stdout_len))
                stdout.seek(0)

                stderr_len = int(f.readline().decode().rstrip())
                stderr = tempfile.NamedTemporaryFile()
                stderr.write(f.read(stderr_len))
                stderr.seek(0)

                result = CompletedCommand(return_code=results_json['return_code'],
                                          timed_out=results_json['timed_out'],
                                          stdout=stdout,
                                          stderr=stderr,
                                          stdout_truncated=results_json['stdout_truncated'],
                                          stderr_truncated=results_json['stderr_truncated'])

                if (result.return_code != 0 or results_json['timed_out']) and check:
                    raise subprocess.CalledProcessError(
                        result.return_code, cmd,
                        output=result.stdout, stderr=result.stderr)

                return result
            except subprocess.CalledProcessError as e:
                f.seek(0)
                print(f.read())
                print(e.stderr)
                raise
def run_command(self,
                    args: List[str],
                    max_num_processes: int=None,
                    max_stack_size: int=None,
                    max_virtual_memory: int=None,
                    as_root: bool=False,
                    stdin: FileIO=None,
                    timeout: int=None,
                    check: bool=False,
                    truncate_stdout: int=None,
                    truncate_stderr: int=None) -> 'CompletedCommand':
        cmd = ['docker', 'exec', '-i', self.name, 'cmd_runner.py']

        if stdin is None:
            cmd.append('--stdin_devnull')

        if max_num_processes is not None:
            cmd += ['--max_num_processes', str(max_num_processes)]

        if max_stack_size is not None:
            cmd += ['--max_stack_size', str(max_stack_size)]

        if max_virtual_memory is not None:
            cmd += ['--max_virtual_memory', str(max_virtual_memory)]

        if timeout is not None:
            cmd += ['--timeout', str(timeout)]

        if truncate_stdout is not None:
            cmd += ['--truncate_stdout', str(truncate_stdout)]

        if truncate_stderr is not None:
            cmd += ['--truncate_stderr', str(truncate_stderr)]

        if not as_root:
            cmd += ['--linux_user_id', str(self._linux_uid)]

        cmd += args

        if self.debug:
            print('running: {}'.format(cmd), flush=True)

        with tempfile.TemporaryFile() as f:
            try:
                subprocess.run(cmd, stdin=stdin, stdout=f, stderr=subprocess.PIPE, check=True)
                f.seek(0)
                json_len = int(f.readline().decode().rstrip())
                results_json = json.loads(f.read(json_len).decode())

                stdout_len = int(f.readline().decode().rstrip())
                stdout = tempfile.NamedTemporaryFile()
                stdout.write(f.read(stdout_len))
                stdout.seek(0)

                stderr_len = int(f.readline().decode().rstrip())
                stderr = tempfile.NamedTemporaryFile()
                stderr.write(f.read(stderr_len))
                stderr.seek(0)

                result = CompletedCommand(return_code=results_json['return_code'],
                                          timed_out=results_json['timed_out'],
                                          stdout=stdout,
                                          stderr=stderr,
                                          stdout_truncated=results_json['stdout_truncated'],
                                          stderr_truncated=results_json['stderr_truncated'])

                if (result.return_code != 0 or results_json['timed_out']) and check:
                    raise subprocess.CalledProcessError(
                        result.return_code, cmd,
                        output=result.stdout, stderr=result.stderr)

                return result
            except subprocess.CalledProcessError as e:
                f.seek(0)
                print(f.read())
                print(e.stderr)
                raise
def run_command ( self , args : List [ str ] , max_num_processes : int = None , max_stack_size : int = None , max_virtual_memory : int = None , as_root : bool = False , stdin : FileIO = None , timeout : int = None , check : bool = False , truncate_stdout : int = None , truncate_stderr : int = None ) -> 'CompletedCommand' : cmd = [ 'docker' , 'exec' , '-i' , self . name , 'cmd_runner.py' ] if stdin is None : cmd . append ( '--stdin_devnull' ) if max_num_processes is not None : cmd += [ '--max_num_processes' , str ( max_num_processes ) ] if max_stack_size is not None : cmd += [ '--max_stack_size' , str ( max_stack_size ) ] if max_virtual_memory is not None : cmd += [ '--max_virtual_memory' , str ( max_virtual_memory ) ] if timeout is not None : cmd += [ '--timeout' , str ( timeout ) ] if truncate_stdout is not None : cmd += [ '--truncate_stdout' , str ( truncate_stdout ) ] if truncate_stderr is not None : cmd += [ '--truncate_stderr' , str ( truncate_stderr ) ] if not as_root : cmd += [ '--linux_user_id' , str ( self . _linux_uid ) ] cmd += args if self . debug : print ( 'running: {}' . format ( cmd ) , flush = True ) with tempfile . TemporaryFile ( ) as f : try : subprocess . run ( cmd , stdin = stdin , stdout = f , stderr = subprocess . PIPE , check = True ) f . seek ( 0 ) json_len = int ( f . readline ( ) . decode ( ) . rstrip ( ) ) results_json = json . loads ( f . read ( json_len ) . decode ( ) ) stdout_len = int ( f . readline ( ) . decode ( ) . rstrip ( ) ) stdout = tempfile . NamedTemporaryFile ( ) stdout . write ( f . read ( stdout_len ) ) stdout . seek ( 0 ) stderr_len = int ( f . readline ( ) . decode ( ) . rstrip ( ) ) stderr = tempfile . NamedTemporaryFile ( ) stderr . write ( f . read ( stderr_len ) ) stderr . seek ( 0 ) result = CompletedCommand ( return_code = results_json [ 'return_code' ] , timed_out = results_json [ 'timed_out' ] , stdout = stdout , stderr = stderr , stdout_truncated = results_json [ 'stdout_truncated' ] , stderr_truncated = results_json [ 'stderr_truncated' ] ) if ( result . return_code != 0 or results_json [ 'timed_out' ] ) and check : raise subprocess . CalledProcessError ( result . return_code , cmd , output = result . stdout , stderr = result . stderr ) return result except subprocess . CalledProcessError as e : f . seek ( 0 ) print ( f . read ( ) ) print ( e . stderr ) raise
Runs a command inside the sandbox and returns the results.

        :param args: A list of strings that specify which command should
            be run inside the sandbox.

        :param max_num_processes: The maximum number of processes the
            command is allowed to spawn.

        :param max_stack_size: The maximum stack size, in bytes, allowed
            for the command.

        :param max_virtual_memory: The maximum amount of memory, in
            bytes, allowed for the command.

        :param as_root: Whether to run the command as a root user.

        :param stdin: A file object to be redirected as input to the
            command's stdin. If this is None, /dev/null is sent to the
            command's stdin.

        :param timeout: The time limit for the command.

        :param check: Causes CalledProcessError to be raised if the
            command exits nonzero or times out.

        :param truncate_stdout: When not None, stdout from the command
            will be truncated after this many bytes.

        :param truncate_stderr: When not None, stderr from the command
            will be truncated after this many bytes.
Runs a command inside the sandbox and returns the results .