Example #1
0
    def start(self):
        """Start the process and the logger pipes for its stdout and stderr."""

        creation_flags = 0
        if sys.platform == "win32" and _JOB_OBJECT is not None:
            creation_flags |= win32process.CREATE_BREAKAWAY_FROM_JOB

        # Tests fail if a process takes too long to startup and listen to a socket. Use buffered
        # I/O pipes to give the process some leeway.
        buffer_size = 1024 * 1024

        # Close file descriptors in the child process before executing the program. This prevents
        # file descriptors that were inherited due to multiple calls to fork() -- either within one
        # thread, or concurrently from multiple threads -- from causing another subprocess to wait
        # for the completion of the newly spawned child process. Closing other file descriptors
        # isn't supported on Windows when stdout and stderr are redirected.
        close_fds = (sys.platform != "win32")

        with _POPEN_LOCK:
            self._process = subprocess.Popen(self.args,
                                             bufsize=buffer_size,
                                             stdout=subprocess.PIPE,
                                             stderr=subprocess.PIPE,
                                             close_fds=close_fds,
                                             env=self.env,
                                             creationflags=creation_flags,
                                             cwd=self._cwd)
            self.pid = self._process.pid

            if _config.UNDO_RECORDER_PATH is not None and (
                    "mongod" in self.args[0] or "mongos" in self.args[0]):
                recorder_args = [
                    _config.UNDO_RECORDER_PATH, "--thread-fuzzing", "-p",
                    str(self.pid)
                ]
                self._recorder = subprocess.Popen(recorder_args,
                                                  bufsize=buffer_size,
                                                  env=self.env,
                                                  creationflags=creation_flags)

        self._stdout_pipe = pipe.LoggerPipe(self.logger, logging.INFO,
                                            self._process.stdout)
        self._stderr_pipe = pipe.LoggerPipe(self.logger, logging.ERROR,
                                            self._process.stderr)

        self._stdout_pipe.wait_until_started()
        self._stderr_pipe.wait_until_started()

        if sys.platform == "win32" and _JOB_OBJECT is not None:
            try:
                win32job.AssignProcessToJobObject(_JOB_OBJECT,
                                                  self._process._handle)
            except win32job.error as err:
                # ERROR_ACCESS_DENIED (winerror=5) is received when the process has already died.
                if err.winerror != winerror.ERROR_ACCESS_DENIED:
                    raise
                return_code = win32process.GetExitCodeProcess(
                    self._process._handle)
                if return_code == win32con.STILL_ACTIVE:
                    raise
Example #2
0
    def _get_log_calls(cls, output):
        logger = logging.Logger("for_testing")
        logger.log = mock.MagicMock()

        logger_pipe = _pipe.LoggerPipe(logger=logger, level=cls.LOG_LEVEL,
                                       pipe_out=io.BytesIO(output))
        logger_pipe.wait_until_started()
        logger_pipe.wait_until_finished()

        return logger.log.call_args_list
Example #3
0
    def start(self):
        """Start the process and the logger pipes for its stdout and stderr."""

        creation_flags = 0
        if sys.platform == "win32" and _JOB_OBJECT is not None:
            creation_flags |= win32process.CREATE_BREAKAWAY_FROM_JOB

        # Tests fail if a process takes too long to startup and listen to a socket. Use buffered
        # I/O pipes to give the process some leeway.
        buffer_size = 1024 * 1024

        # Close file descriptors in the child process before executing the program. This prevents
        # file descriptors that were inherited due to multiple calls to fork() -- either within one
        # thread, or concurrently from multiple threads -- from causing another subprocess to wait
        # for the completion of the newly spawned child process. Closing other file descriptors
        # isn't supported on Windows when stdout and stderr are redirected.
        close_fds = (sys.platform != "win32")

        with _POPEN_LOCK:

            # Record unittests directly since resmoke doesn't not interact with them and they can finish
            # too quickly for the recorder to have a chance at attaching.
            recorder_args = []
            if _config.UNDO_RECORDER_PATH is not None and self.args[
                    0].endswith("_test"):
                now_str = datetime.now().strftime("%Y-%m-%dT%H-%M-%S")
                # Only use the process name since we have to be able to correlate the recording name
                # with the binary name easily.
                recorder_output_file = "{process}-{t}.undo".format(
                    process=os.path.basename(self.args[0]), t=now_str)
                recorder_args = [
                    _config.UNDO_RECORDER_PATH, "-o", recorder_output_file
                ]

            self._process = subprocess.Popen(recorder_args + self.args,
                                             bufsize=buffer_size,
                                             stdout=subprocess.PIPE,
                                             stderr=subprocess.PIPE,
                                             close_fds=close_fds,
                                             env=self.env,
                                             creationflags=creation_flags,
                                             cwd=self._cwd)
            self.pid = self._process.pid

            if _config.UNDO_RECORDER_PATH is not None and (
                    not self.args[0].endswith("_test")) and (
                        "mongod" in self.args[0] or "mongos" in self.args[0]):
                now_str = datetime.now().strftime("%Y-%m-%dT%H-%M-%S")
                recorder_output_file = "{logger}-{process}-{pid}-{t}.undo".format(
                    logger=self.logger.name.replace('/', '-'),
                    process=os.path.basename(self.args[0]),
                    pid=self.pid,
                    t=now_str)
                recorder_args = [
                    _config.UNDO_RECORDER_PATH, "-p",
                    str(self.pid), "-o", recorder_output_file
                ]
                self._recorder = subprocess.Popen(recorder_args,
                                                  bufsize=buffer_size,
                                                  env=self.env,
                                                  creationflags=creation_flags)

        self._stdout_pipe = pipe.LoggerPipe(self.logger, logging.INFO,
                                            self._process.stdout)
        self._stderr_pipe = pipe.LoggerPipe(self.logger, logging.ERROR,
                                            self._process.stderr)

        self._stdout_pipe.wait_until_started()
        self._stderr_pipe.wait_until_started()

        if sys.platform == "win32" and _JOB_OBJECT is not None:
            try:
                win32job.AssignProcessToJobObject(_JOB_OBJECT,
                                                  self._process._handle)
            except win32job.error as err:
                # ERROR_ACCESS_DENIED (winerror=5) is received when the process has already died.
                if err.winerror != winerror.ERROR_ACCESS_DENIED:
                    raise
                return_code = win32process.GetExitCodeProcess(
                    self._process._handle)
                if return_code == win32con.STILL_ACTIVE:
                    raise