<commit_before>#!/usr/bin/env python
# -*- coding: utf-8 -*-

#$HeadURL$
#$LastChangedDate$
#$LastChangedRevision$

# See LICENSE.txt for licensing terms

'''
Copyright (c) 2009,  <NAME>, Austin, Texas

A wrapper around subprocess that performs two functions:

 1) Adds non-blocking I/O
 2) Adds process killability and timeouts

Currently only works under Linux.

'''

import sys
import subprocess
import select
import os
import time
import textwrap
from signal import SIGTERM, SIGKILL
import traceback

class BaseExec(object):
    ''' BaseExec is designed to be subclassed.
        It wraps subprocess.Popen, and adds the
        ability to kill a process and to manage
        timeouts.  By default, it uses pipes for
        the new process, but doesn't do anything
        with them.
    '''
    is_python_proc = False
    defaults = dict(
                bufsize=0,
                executable=None,
                stdin=subprocess.PIPE,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                preexec_fn=None,   # Callable object in child process
                close_fds=False,   
                shell=False,
                cwd=None,
                env=None,
                universal_newlines=False,
                startupinfo=None,
                creationflags=0,
                timeout=500.0,    # Time in seconds before termination
                killdelay=20.0,   # Time in seconds after termination before kill
                python_proc=None,
    )

    def before_init(self, keywords):
        # Replace this in subclass to do more setup
        pass

    def after_init(self):
        # Replace this in subclass to execute code after
        # process creation
        pass

    def wrap_python_exec(self, preexec_fn):
        # Don't let anything in our buffer wrap back into new process
        # Otherwise, it might (will!) come out twice...
        sys.stdout.flush()
        sys.stderr.flush()
        self.is_python_proc = True

        def wrapper():
            sys.argv = self.args
            try:
                preexec_fn()
            except Exception:
                print >> sys.stderr, traceback.format_exc()
                sys.stderr.write(chr(1))
        return wrapper

    def __init__(self, *args, **kw):

        # Allow flexible args handling.
        if len(args) < 2:
            try:
                args[0] + ''
            except TypeError:
                args = args[0]
            else:
                args = args[0].split()
        self.args = args

        # Handle defaults
        keywords = self.defaults.copy()
        keywords.update(kw)

        # Get our timeout information, and call
        # subclass to get other parameters
        self.timeout = keywords.pop('timeout') + time.time()
        self.killdelay = keywords.pop('killdelay')
        self.before_init(keywords)

        # Handle any special Python proc
        python_proc = keywords.pop('python_proc')
        if python_proc is not None:
            assert keywords.pop('preexec_fn') is None
            keywords['preexec_fn'] = self.wrap_python_exec(python_proc)
            args = ['true']
<commit_msg>Fixed autotest -f (fast mode) output when spawned interpreter raises SystemExit (e.g. by calling sys.exit).  Test case for issue 247 was exiting outermost interpreter before this fix.<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*-

#$HeadURL$
#$LastChangedDate$
#$LastChangedRevision$

# See LICENSE.txt for licensing terms

'''
Copyright (c) 2009,  <NAME>, Austin, Texas

A wrapper around subprocess that performs two functions:

 1) Adds non-blocking I/O
 2) Adds process killability and timeouts

Currently only works under Linux.

'''

import sys
import subprocess
import select
import os
import time
import textwrap
from signal import SIGTERM, SIGKILL
import traceback

class BaseExec(object):
    ''' BaseExec is designed to be subclassed.
        It wraps subprocess.Popen, and adds the
        ability to kill a process and to manage
        timeouts.  By default, it uses pipes for
        the new process, but doesn't do anything
        with them.
    '''
    is_python_proc = False
    defaults = dict(
                bufsize=0,
                executable=None,
                stdin=subprocess.PIPE,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                preexec_fn=None,   # Callable object in child process
                close_fds=False,   
                shell=False,
                cwd=None,
                env=None,
                universal_newlines=False,
                startupinfo=None,
                creationflags=0,
                timeout=500.0,    # Time in seconds before termination
                killdelay=20.0,   # Time in seconds after termination before kill
                python_proc=None,
    )

    def before_init(self, keywords):
        # Replace this in subclass to do more setup
        pass

    def after_init(self):
        # Replace this in subclass to execute code after
        # process creation
        pass

    def wrap_python_exec(self, preexec_fn):
        # Don't let anything in our buffer wrap back into new process
        # Otherwise, it might (will!) come out twice...
        sys.stdout.flush()
        sys.stderr.flush()
        self.is_python_proc = True

        def wrapper():
            sys.argv = self.args
            try:
                preexec_fn()
            except Exception:
                sys.stdout.flush()
                print >> sys.stderr, traceback.format_exc()
                sys.stderr.write(chr(1))
            except SystemExit, s:
                sys.stdout.flush()
                code = s.code
                try:
                    code = int(code)
                except:
                    pass
                if code:
                    print >> sys.stderr, code
                    sys.stderr.write(chr(1))
        return wrapper

    def __init__(self, *args, **kw):

        # Allow flexible args handling.
        if len(args) < 2:
            try:
                args[0] + ''
            except TypeError:
                args = args[0]
            else:
                args = args[0].split()
        self.args = args

        # Handle defaults
        keywords = self.defaults.copy()
        keywords.update(kw)

        # Get our timeout information, and call
        # subclass to get other parameters
        self.timeout = keywords.pop('timeout') + time.time()
        self.killdelay = keywords.pop('killdelay')
        self.before_init(keywords)

        # Handle any special Python proc
        python_proc = keywords.pop('python_proc')
        if python_proc is not None:
            assert keywords.pop('preexec_fn') is None
            keywords['preexec_fn'] = self.wrap_python_exec(python_proc)
            args = ['true']

{'fraction_non_alphanumeric': 0.0804647785039942, 'fraction_numerical': 0.006681190994916485, 'mean_word_length': 1.7445197289756875, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4637873', 'n_tokens_mistral': 1941, 'n_tokens_neox': 1798, 'n_words': 570}