Exemple #1
0
        def which(program, paths):
            def is_exe(fpath):
                return os.path.exists(fpath) and os.access(fpath, os.X_OK)

            for path in paths:
                if not os.path.isdir(path):
                    continue
                exe_file = os.path.join(u(path, fs_encoding), program)
                if is_exe(exe_file):
                    return file_quote(exe_file)
            return None
Exemple #2
0
        def which(program, paths):
            def is_exe(fpath):
                return os.path.exists(fpath) and os.access(fpath, os.X_OK)

            for path in paths:
                if not os.path.isdir(path):
                    continue
                exe_file = os.path.join(u(path, fs_encoding), program)
                if is_exe(exe_file):
                    return file_quote(exe_file)
            return None
Exemple #3
0
    def start(self, cb=None):
        def which(program, paths):
            def is_exe(fpath):
                return os.path.exists(fpath) and os.access(fpath, os.X_OK)

            for path in paths:
                if not os.path.isdir(path):
                    continue
                exe_file = os.path.join(u(path, fs_encoding), program)
                if is_exe(exe_file):
                    return file_quote(exe_file)
            return None

        def convert_environment_variables(env):
            """
            This function is use to convert environment variable to string
            because environment variable must be string in popen
            :param env: Dict of environment variable
            :return: Encoded environment variable as string
            """
            encoding = sys.getfilesystemencoding()
            if encoding is None or encoding == 'ascii':
                encoding = 'utf-8'
            temp_env = dict()
            for key, value in env.items():
                if not isinstance(key, str):
                    key = key.encode(encoding)
                if not isinstance(value, str):
                    value = value.encode(encoding)
                temp_env[key] = value
            return temp_env

        if self.stime is not None:
            if self.etime is None:
                raise Exception(_('The process has already been started.'))
            raise Exception(
                _('The process has already finished and cannot be restarted.'))

        executor = file_quote(
            os.path.join(os.path.dirname(u(__file__)), u'process_executor.py'))
        paths = os.environ['PATH'].split(os.pathsep)
        interpreter = None

        if os.name == 'nt':
            paths.insert(0, os.path.join(u(sys.prefix), u'Scripts'))
            paths.insert(0, u(sys.prefix))

            interpreter = which(u'pythonw.exe', paths)
            if interpreter is None:
                interpreter = which(u'python.exe', paths)

            if interpreter is None and current_app.PGADMIN_RUNTIME:
                # We've faced an issue with Windows 2008 R2 (x86) regarding,
                # not honouring the environment variables set under the Qt
                # (e.g. runtime), and also setting PYTHONHOME same as
                # sys.executable (i.e. pgAdmin4.exe).
                #
                # As we know, we're running it under the runtime, we can assume
                # that 'venv' directory will be available outside of 'bin'
                # directory.
                #
                # We would try out luck to find python executable based on that
                # assumptions.
                bin_path = os.path.dirname(sys.executable)

                venv = os.path.realpath(os.path.join(bin_path, u'..\\venv'))

                interpreter = which(u'pythonw.exe', [venv])
                if interpreter is None:
                    interpreter = which(u'pythonw.exe', [venv])

                if interpreter is not None:
                    # Our assumptions are proven right.
                    # Let's append the 'bin' directory to the PATH environment
                    # variable. And, also set PYTHONHOME environment variable
                    # to 'venv' directory.
                    os.environ['PATH'] = bin_path + ';' + os.environ['PATH']
                    os.environ['PYTHONHOME'] = venv
        else:
            # Let's not use sys.prefix in runtime.
            # 'sys.prefix' is not identified on *nix systems for some unknown
            # reason, while running under the runtime.
            # We're already adding '<installation path>/pgAdmin 4/venv/bin'
            # directory in the PATH environment variable. Hence - it will
            # anyway be the redundant value in paths.
            if not current_app.PGADMIN_RUNTIME:
                paths.insert(0, os.path.join(u(sys.prefix), u'bin'))
            interpreter = which(u'python', paths)

        p = None
        cmd = [
            interpreter if interpreter is not None else 'python', executor,
            self.cmd
        ]
        cmd.extend(self.args)

        if os.name == 'nt' and IS_PY2:
            command = []
            for c in cmd:
                command.append(
                    c.encode('utf-8') if isinstance(c, unicode) else str(c))

            current_app.logger.info(
                u"Executing the process executor with the arguments: %s",
                ''.join(command))

            cmd = command
        else:
            current_app.logger.info(
                u"Executing the process executor with the arguments: %s",
                str(cmd))

        # Make a copy of environment, and add new variables to support
        env = os.environ.copy()
        env['PROCID'] = self.id
        env['OUTDIR'] = self.log_dir
        env['PGA_BGP_FOREGROUND'] = "1"

        if cb is not None:
            cb(env)

        if IS_PY2:
            # We need environment variables & values in string
            env = convert_environment_variables(env)

        if os.name == 'nt':
            DETACHED_PROCESS = 0x00000008
            from subprocess import CREATE_NEW_PROCESS_GROUP

            # We need to redirect the standard input, standard output, and
            # standard error to devnull in order to allow it start in detached
            # mode on
            stdout = os.devnull
            stderr = stdout
            stdin = open(os.devnull, "r")
            stdout = open(stdout, "a")
            stderr = open(stderr, "a")

            p = Popen(cmd,
                      close_fds=False,
                      env=env,
                      stdout=stdout.fileno(),
                      stderr=stderr.fileno(),
                      stdin=stdin.fileno(),
                      creationflags=(CREATE_NEW_PROCESS_GROUP
                                     | DETACHED_PROCESS))
        else:

            def preexec_function():
                import signal
                # Detaching from the parent process group
                os.setpgrp()
                # Explicitly ignoring signals in the child process
                signal.signal(signal.SIGINT, signal.SIG_IGN)

            p = Popen(cmd,
                      close_fds=True,
                      stdout=None,
                      stderr=None,
                      stdin=None,
                      preexec_fn=preexec_function,
                      env=env)

        self.ecode = p.poll()

        # Execution completed immediately.
        # Process executor cannot update the status, if it was not able to
        # start properly.
        if self.ecode is not None and self.ecode != 0:
            # There is no way to find out the error message from this process
            # as standard output, and standard error were redirected to
            # devnull.
            p = Process.query.filter_by(pid=self.id,
                                        user_id=current_user.id).first()
            p.start_time = p.end_time = get_current_time()
            if not p.exit_code:
                p.exit_code = self.ecode
            db.session.commit()
Exemple #4
0
        if scheme:
            environ["wsgi.url_scheme"] = scheme
        return self.app(environ, start_response)


##########################################################################
# Sanity checks
##########################################################################
config.SETTINGS_SCHEMA_VERSION = SCHEMA_VERSION

# Check if the database exists. If it does not, create it.
if not os.path.isfile(config.SQLITE_PATH):
    setup_py = os.path.join(
        os.path.dirname(os.path.realpath(u(__file__, fs_encoding))),
        u'setup.py')
    exec(open(file_quote(setup_py), 'r').read())

##########################################################################
# Create the app and configure it. It is created outside main so that
# it can be imported
##########################################################################
app = create_app()
app.debug = False
if config.SERVER_MODE:
    app.wsgi_app = ReverseProxied(app.wsgi_app)

# Authentication sources
app.PGADMIN_DEFAULT_AUTH_SOURCE = 'internal'
app.PGADMIN_SUPPORTED_AUTH_SOURCE = ['internal', 'ldap']
if len(config.AUTHENTICATION_SOURCES) > 0:
    app.PGADMIN_EXTERNAL_AUTH_SOURCE = config.AUTHENTICATION_SOURCES[0]
Exemple #5
0
    def start(self, cb=None):
        self.check_start_end_time()

        executor = file_quote(
            os.path.join(os.path.dirname(u_encode(__file__)),
                         'process_executor.py'))
        paths = os.environ['PATH'].split(os.pathsep)

        current_app.logger.info("Process Executor: Operating System Path %s",
                                str(paths))

        interpreter = self.get_interpreter(paths)

        p = None
        cmd = [
            interpreter if interpreter is not None else 'python', executor,
            self.cmd
        ]
        cmd.extend(self.args)

        current_app.logger.info(
            "Executing the process executor with the arguments: %s", str(cmd))

        # Make a copy of environment, and add new variables to support
        env = os.environ.copy()
        env['PROCID'] = self.id
        env['OUTDIR'] = self.log_dir
        env['PGA_BGP_FOREGROUND'] = "1"

        if self.env:
            env.update(self.env)

        if cb is not None:
            cb(env)

        if os.name == 'nt':
            DETACHED_PROCESS = 0x00000008
            from subprocess import CREATE_NEW_PROCESS_GROUP

            # We need to redirect the standard input, standard output, and
            # standard error to devnull in order to allow it start in detached
            # mode on
            stdout = os.devnull
            stderr = stdout
            stdin = open(os.devnull, "r")
            stdout = open(stdout, "a")
            stderr = open(stderr, "a")

            p = Popen(cmd,
                      close_fds=False,
                      env=env,
                      stdout=stdout.fileno(),
                      stderr=stderr.fileno(),
                      stdin=stdin.fileno(),
                      creationflags=(CREATE_NEW_PROCESS_GROUP
                                     | DETACHED_PROCESS))
        else:
            # if in debug mode, wait for process to complete and
            # get the stdout and stderr of popen.
            if config.CONSOLE_LOG_LEVEL <= logging.DEBUG:
                output, error = self.get_process_output(cmd, env)
            else:
                p = Popen(cmd,
                          close_fds=True,
                          stdout=None,
                          stderr=None,
                          stdin=None,
                          preexec_fn=self.preexec_function,
                          env=env)

        self.ecode = p.poll()

        # Execution completed immediately.
        # Process executor cannot update the status, if it was not able to
        # start properly.
        if self.ecode is not None and self.ecode != 0:
            # There is no way to find out the error message from this process
            # as standard output, and standard error were redirected to
            # devnull.
            p = Process.query.filter_by(pid=self.id,
                                        user_id=current_user.id).first()
            p.start_time = p.end_time = get_current_time()
            if not p.exit_code:
                p.exit_code = self.ecode
            p.process_state = PROCESS_FINISHED
            db.session.commit()
        else:
            # Update the process state to "Started"
            p = Process.query.filter_by(pid=self.id,
                                        user_id=current_user.id).first()
            p.process_state = PROCESS_STARTED
            db.session.commit()
Exemple #6
0
    def start(self, cb=None):

        def which(program, paths):
            def is_exe(fpath):
                return os.path.exists(fpath) and os.access(fpath, os.X_OK)

            for path in paths:
                if not os.path.isdir(path):
                    continue
                exe_file = os.path.join(u_encode(path, fs_encoding), program)
                if is_exe(exe_file):
                    return file_quote(exe_file)
            return None

        if self.stime is not None:
            if self.etime is None:
                raise RuntimeError(_('The process has already been started.'))
            raise RuntimeError(
                _('The process has already finished and cannot be restarted.')
            )

        executor = file_quote(os.path.join(
            os.path.dirname(u_encode(__file__)), u'process_executor.py'
        ))
        paths = os.environ['PATH'].split(os.pathsep)
        interpreter = None

        current_app.logger.info(
            u"Process Executor: Operating System Path %s",
            str(paths)
        )

        if os.name == 'nt':
            paths.insert(0, os.path.join(u_encode(sys.prefix), u'Scripts'))
            paths.insert(0, u_encode(sys.prefix))

            interpreter = which(u'pythonw.exe', paths)
            if interpreter is None:
                interpreter = which(u'python.exe', paths)

            current_app.logger.info(
                u"Process Executor: Interpreter value in path: %s",
                str(interpreter)
            )
            if interpreter is None and current_app.PGADMIN_RUNTIME:
                # We've faced an issue with Windows 2008 R2 (x86) regarding,
                # not honouring the environment variables set under the Qt
                # (e.g. runtime), and also setting PYTHONHOME same as
                # sys.executable (i.e. pgAdmin4.exe).
                #
                # As we know, we're running it under the runtime, we can assume
                # that 'venv' directory will be available outside of 'bin'
                # directory.
                #
                # We would try out luck to find python executable based on that
                # assumptions.
                bin_path = os.path.dirname(sys.executable)

                venv = os.path.realpath(
                    os.path.join(bin_path, u'..\\venv')
                )

                interpreter = which(u'pythonw.exe', [venv])
                if interpreter is None:
                    interpreter = which(u'python.exe', [venv])

                current_app.logger.info(
                    u"Process Executor: Interpreter value in virtual "
                    u"environment: %s", str(interpreter)
                )

                if interpreter is not None:
                    # Our assumptions are proven right.
                    # Let's append the 'bin' directory to the PATH environment
                    # variable. And, also set PYTHONHOME environment variable
                    # to 'venv' directory.
                    os.environ['PATH'] = bin_path + ';' + os.environ['PATH']
                    os.environ['PYTHONHOME'] = venv
        else:
            # Let's not use sys.prefix in runtime.
            # 'sys.prefix' is not identified on *nix systems for some unknown
            # reason, while running under the runtime.
            # We're already adding '<installation path>/pgAdmin 4/venv/bin'
            # directory in the PATH environment variable. Hence - it will
            # anyway be the redundant value in paths.
            if not current_app.PGADMIN_RUNTIME:
                paths.insert(0, os.path.join(u_encode(sys.prefix), u'bin'))
            python_binary_name = 'python{0}'.format(sys.version_info[0])
            interpreter = which(u_encode(python_binary_name), paths)

        p = None
        cmd = [
            interpreter if interpreter is not None else 'python',
            executor, self.cmd
        ]
        cmd.extend(self.args)

        current_app.logger.info(
            u"Executing the process executor with the arguments: %s",
            str(cmd)
        )

        # Make a copy of environment, and add new variables to support
        env = os.environ.copy()
        env['PROCID'] = self.id
        env['OUTDIR'] = self.log_dir
        env['PGA_BGP_FOREGROUND'] = "1"

        if self.env:
            env.update(self.env)

        if cb is not None:
            cb(env)

        if os.name == 'nt':
            DETACHED_PROCESS = 0x00000008
            from subprocess import CREATE_NEW_PROCESS_GROUP

            # We need to redirect the standard input, standard output, and
            # standard error to devnull in order to allow it start in detached
            # mode on
            stdout = os.devnull
            stderr = stdout
            stdin = open(os.devnull, "r")
            stdout = open(stdout, "a")
            stderr = open(stderr, "a")

            p = Popen(
                cmd,
                close_fds=False,
                env=env,
                stdout=stdout.fileno(),
                stderr=stderr.fileno(),
                stdin=stdin.fileno(),
                creationflags=(CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS)
            )
        else:
            def preexec_function():
                import signal
                # Detaching from the parent process group
                os.setpgrp()
                # Explicitly ignoring signals in the child process
                signal.signal(signal.SIGINT, signal.SIG_IGN)

            # if in debug mode, wait for process to complete and
            # get the stdout and stderr of popen.
            if config.CONSOLE_LOG_LEVEL <= logging.DEBUG:
                p = Popen(
                    cmd, close_fds=True, stdout=PIPE, stderr=PIPE, stdin=None,
                    preexec_fn=preexec_function, env=env
                )

                output, errors = p.communicate()
                output = output.decode() \
                    if hasattr(output, 'decode') else output
                errors = errors.decode() \
                    if hasattr(errors, 'decode') else errors
                current_app.logger.debug(
                    'Process Watcher Out:{0}'.format(output))
                current_app.logger.debug(
                    'Process Watcher Err:{0}'.format(errors))
            else:
                p = Popen(
                    cmd, close_fds=True, stdout=None, stderr=None, stdin=None,
                    preexec_fn=preexec_function, env=env
                )

        self.ecode = p.poll()

        # Execution completed immediately.
        # Process executor cannot update the status, if it was not able to
        # start properly.
        if self.ecode is not None and self.ecode != 0:
            # There is no way to find out the error message from this process
            # as standard output, and standard error were redirected to
            # devnull.
            p = Process.query.filter_by(
                pid=self.id, user_id=current_user.id
            ).first()
            p.start_time = p.end_time = get_current_time()
            if not p.exit_code:
                p.exit_code = self.ecode
            p.process_state = PROCESS_FINISHED
            db.session.commit()
        else:
            # Update the process state to "Started"
            p = Process.query.filter_by(
                pid=self.id, user_id=current_user.id
            ).first()
            p.process_state = PROCESS_STARTED
            db.session.commit()
Exemple #7
0
def detached_process(p_cmd, p_ctime=None, report_file=None, stdin_str=None, is_local=False, process_type=None, exclude_str=None):


    executor = file_quote(os.path.join(
        os.path.dirname(u(__file__)), u'process_executor.py'
    ))

    if is_local:
        executor = file_quote(os.path.join(
            os.path.dirname(u(__file__)), u'local_process_executor.py'
        ))
    paths = sys.path[:]
    interpreter = None

    if os.name == 'nt':
        paths.insert(0, os.path.join(u(sys.prefix), u'Scripts'))
        paths.insert(0, u(sys.prefix))

        interpreter = which(u'pythonw.exe', paths)
        if interpreter is None:
            interpreter = which(u'python.exe', paths)
    else:
        paths.insert(0, os.path.join(u(sys.prefix), u'bin'))
        interpreter = which(u'python', paths)

    p = None
    cmd = [
        interpreter if interpreter is not None else 'python',
        executor, p_cmd
    ]
    #cmd.extend(self.args)

    if not p_ctime:
        ctime = get_current_time(format='%y%m%d%H%M%S%f')
    else:
        ctime = p_ctime
    log_dir = os.path.join(
        config.SESSION_DB_PATH, 'process_logs'
    )
    if not os.path.exists(log_dir):
        os.mkdir(log_dir)
    id = ctime
    log_dir = os.path.join(log_dir, id)
    if not os.path.exists(log_dir):
        os.mkdir(log_dir)
    # Make a copy of environment, and add new variables to support
    env = os.environ.copy()
    env['PROCID'] = id
    env['OUTDIR'] = log_dir
    env['PGA_BGP_FOREGROUND'] = "1"
    if stdin_str:
        env['stdin_str'] = stdin_str
    if report_file:
        env['report_file'] = report_file
    if process_type:
        env['process_type'] = process_type
    if exclude_str:
        env["EXCLUDE_STR"] = exclude_str
    if IS_PY2:
        # We need environment variables & values in string
        env = convert_environment_variables(env)

    if os.name == 'nt':
        DETACHED_PROCESS = 0x00000008
        from subprocess import CREATE_NEW_PROCESS_GROUP

        # We need to redirect the standard input, standard output, and
        # standard error to devnull in order to allow it start in detached
        # mode on
        stdout = os.devnull
        stderr = stdout
        stdin = open(os.devnull, "r")
        stdout = open(stdout, "a")
        stderr = open(stderr, "a")

        p = Popen(
            cmd, close_fds=False, env=env, stdout=stdout.fileno(),
            stderr=stderr.fileno(), stdin=stdin.fileno(),
            creationflags=(CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS)
        )
    else:
        def preexec_function():
            import signal
            # Detaching from the parent process group
            os.setpgrp()
            # Explicitly ignoring signals in the child process
            #signal.signal(signal.SIGINT, signal.SIG_IGN)

        p = Popen(
            cmd, close_fds=True, stdout=None, stderr=None, stdin=None,
            preexec_fn=preexec_function, env=env
        )

    ecode = p.poll()

    # Execution completed immediately.
    # Process executor can not update the status, if it was not able to
    # start properly.
    process_completed=False
    if ecode is not None and ecode != 0:
        # There is no way to find out the error message from this process
        # as standard output, and standard error were redirected to
        # devnull.
        process_completed=True
    return {"status":process_completed, "log_dir":log_dir, 'process_log_id':id}
Exemple #8
0
    def start(self, cb=None):

        def which(program, paths):
            def is_exe(fpath):
                return os.path.exists(fpath) and os.access(fpath, os.X_OK)

            for path in paths:
                if not os.path.isdir(path):
                    continue
                exe_file = os.path.join(u(path, fs_encoding), program)
                if is_exe(exe_file):
                    return file_quote(exe_file)
            return None

        def convert_environment_variables(env):
            """
            This function is use to convert environment variable to string
            because environment variable must be string in popen
            :param env: Dict of environment variable
            :return: Encoded environment variable as string
            """
            encoding = sys.getdefaultencoding()
            if encoding is None or encoding == 'ascii':
                encoding = 'utf-8'
            temp_env = dict()
            for key, value in env.items():
                if not isinstance(key, str):
                    key = key.encode(encoding)
                if not isinstance(value, str):
                    value = value.encode(encoding)
                temp_env[key] = value
            return temp_env

        if self.stime is not None:
            if self.etime is None:
                raise Exception(_('The process has already been started.'))
            raise Exception(
                _('The process has already finished and cannot be restarted.')
            )

        executor = file_quote(os.path.join(
            os.path.dirname(u(__file__)), u'process_executor.py'
        ))
        paths = os.environ['PATH'].split(os.pathsep)
        interpreter = None

        if os.name == 'nt':
            paths.insert(0, os.path.join(u(sys.prefix), u'Scripts'))
            paths.insert(0, u(sys.prefix))

            interpreter = which(u'pythonw.exe', paths)
            if interpreter is None:
                interpreter = which(u'python.exe', paths)

            if interpreter is None and current_app.PGADMIN_RUNTIME:
                # We've faced an issue with Windows 2008 R2 (x86) regarding,
                # not honouring the environment variables set under the Qt
                # (e.g. runtime), and also setting PYTHONHOME same as
                # sys.executable (i.e. pgAdmin4.exe).
                #
                # As we know, we're running it under the runtime, we can assume
                # that 'venv' directory will be available outside of 'bin'
                # directory.
                #
                # We would try out luck to find python executable based on that
                # assumptions.
                bin_path = os.path.dirname(sys.executable)

                venv = os.path.realpath(
                    os.path.join(bin_path, u'..\\venv')
                )

                interpreter = which(u'pythonw.exe', [venv])
                if interpreter is None:
                    interpreter = which(u'pythonw.exe', [venv])

                if interpreter is not None:
                    # Our assumptions are proven right.
                    # Let's append the 'bin' directory to the PATH environment
                    # variable. And, also set PYTHONHOME environment variable
                    # to 'venv' directory.
                    os.environ['PATH'] = bin_path + ';' + os.environ['PATH']
                    os.environ['PYTHONHOME'] = venv
        else:
            # Let's not use sys.prefix in runtime.
            # 'sys.prefix' is not identified on *nix systems for some unknown
            # reason, while running under the runtime.
            # We're already adding '<installation path>/pgAdmin 4/venv/bin'
            # directory in the PATH environment variable. Hence - it will
            # anyway be the redundant value in paths.
            if not current_app.PGADMIN_RUNTIME:
                paths.insert(0, os.path.join(u(sys.prefix), u'bin'))
            interpreter = which(u'python', paths)

        p = None
        cmd = [
            interpreter if interpreter is not None else 'python',
            executor, self.cmd
        ]
        cmd.extend(self.args)

        if os.name == 'nt' and IS_PY2:
            command = []
            for c in cmd:
                command.append(
                    c.encode('utf-8') if isinstance(c, unicode) else str(c)
                )

            current_app.logger.info(
                u"Executing the process executor with the arguments: %s",
                ''.join(command)
            )

            cmd = command
        else:
            current_app.logger.info(
                u"Executing the process executor with the arguments: %s",
                str(cmd)
            )

        # Make a copy of environment, and add new variables to support
        env = os.environ.copy()
        env['PROCID'] = self.id
        env['OUTDIR'] = self.log_dir
        env['PGA_BGP_FOREGROUND'] = "1"

        if self.env:
            env.update(self.env)

        if cb is not None:
            cb(env)

        if IS_PY2:
            # We need environment variables & values in string
            env = convert_environment_variables(env)

        if os.name == 'nt':
            DETACHED_PROCESS = 0x00000008
            from subprocess import CREATE_NEW_PROCESS_GROUP

            # We need to redirect the standard input, standard output, and
            # standard error to devnull in order to allow it start in detached
            # mode on
            stdout = os.devnull
            stderr = stdout
            stdin = open(os.devnull, "r")
            stdout = open(stdout, "a")
            stderr = open(stderr, "a")

            p = Popen(
                cmd,
                close_fds=False,
                env=env,
                stdout=stdout.fileno(),
                stderr=stderr.fileno(),
                stdin=stdin.fileno(),
                creationflags=(CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS)
            )
        else:
            def preexec_function():
                import signal
                # Detaching from the parent process group
                os.setpgrp()
                # Explicitly ignoring signals in the child process
                signal.signal(signal.SIGINT, signal.SIG_IGN)

            p = Popen(
                cmd, close_fds=True, stdout=None, stderr=None, stdin=None,
                preexec_fn=preexec_function, env=env
            )

        self.ecode = p.poll()

        # Execution completed immediately.
        # Process executor cannot update the status, if it was not able to
        # start properly.
        if self.ecode is not None and self.ecode != 0:
            # There is no way to find out the error message from this process
            # as standard output, and standard error were redirected to
            # devnull.
            p = Process.query.filter_by(
                pid=self.id, user_id=current_user.id
            ).first()
            p.start_time = p.end_time = get_current_time()
            if not p.exit_code:
                p.exit_code = self.ecode
            db.session.commit()