Runs non-interactive external commands in FIFO order using a single QProcess.
More...
|
| void | drained () |
| | Emitted once the last queued item is done and nothing runs or waits any more (isIdle()), after that item's finished() or error().
|
| void | finished (int id, int exitCode, const QString &output, const QString &errout) |
| | Emitted when a queued process exits normally, whatever its exit code; a non-zero code is the receiver's to interpret (Pass does).
|
| void | starting () |
| | Emitted just before a queued process is started; the main window shows the busy indicator on it.
|
| void | dequeuing (int id, bool completes) |
| | Emitted, synchronously, when the queue's head leaves it: just before it is started, when it cannot be (no executable, a failed start), or when cancelNext() drops it. Lets a caller do per-item work at the moment the item actually runs, not when it was queued.
|
| void | error (int id, int exitCode, const QString &output, const QString &errout) |
| | Emitted instead of finished() when a queued process could not be started, had no executable configured, or crashed.
|
|
| | Executor (QObject *parent=nullptr) |
| | Construct an Executor with an optional parent QObject.
|
| void | execute (int id, const QString &app, const QStringList &args, bool readStdout, bool readStderr=true) |
| | Queue a command without stdin input.
|
| void | execute (int id, const QString &workDir, const QString &app, const QStringList &args, bool readStdout, bool readStderr=true) |
| | Queue a command with an explicit working directory.
|
| void | execute (int id, const QString &app, const QStringList &args, QString input=QString(), bool readStdout=false, bool readStderr=true) |
| | Queue a command with optional stdin input.
|
| void | execute (int id, const QString &workDir, const QString &app, const QStringList &args, QString input=QString(), bool readStdout=false, bool readStderr=true) |
| | Queue a command with working directory and optional stdin input.
|
| void | setEnvironment (const QProcessEnvironment &env) |
| | Set the environment passed to all child processes.
|
| auto | environment () const -> QProcessEnvironment |
| | Return the environment passed to child processes.
|
| auto | cancelNext () -> int |
| | Cancel the next queued command without executing it.
|
| auto | isIdle () const -> bool |
| | Whether no command is running and nothing is queued.
|
| auto | hasQueued (int id) const -> bool |
| | Whether a command with process id id is queued or running.
|
|
| static auto | executeBlocking (const QString &app, const QStringList &args, const QString &input=QString(), QString *process_out=nullptr, QString *process_err=nullptr) -> int |
| | Run a command synchronously and return its exit code.
|
| static auto | executeBlocking (QProcess &process, const QString &app, const QStringList &args, const QString &input=QString(), QString *process_out=nullptr, QString *process_err=nullptr, const std::atomic_bool *cancel=nullptr, int timeoutMs=-1) -> int |
| | Run a command synchronously on a caller-supplied QProcess, with optional cancellation.
|
| static auto | executeBlocking (const QString &app, const QStringList &args, QString *process_out, QString *process_err=nullptr) -> int |
| | Run a command synchronously capturing stdout and stderr.
|
| static auto | executeBlocking (const QProcessEnvironment &env, const QString &app, const QStringList &args, QString *process_out=nullptr, QString *process_err=nullptr) -> int |
| | Run a command synchronously with a custom environment.
|
| static auto | resolveExecutable (const QString &app) -> QString |
| | The one rule for turning a configured executable into what runs.
|
| static void | detachFromTerminal (QProcess &process) |
| | Make process start its child without a controlling terminal.
|
| static void | setChildUmask (int mask) |
| | The umask every child QtPass starts gets, as pass sets its own.
|
| static auto | childUmask () -> int |
| | The umask setChildUmask() set.
|
| static auto | parseWslCommand (const QString &app) -> std::optional< WslCommand > |
| | Parse a configured executable as a WSL command.
|
| static auto | wslExecArgs (const QString &command, const QStringList &args) -> QStringList |
| | Build the wsl.exe argument list that runs command directly.
|
| static auto | translatePathForWsl (const QString &path, const QString &exe) -> QString |
| | Translate a native path for a WSL-routed executable.
|
|
| static void | startProcess (QProcess &process, const QString &app, const QStringList &args) |
| | Start process running app, handling the "wsl " prefix once for both the queued and the blocking path.
|
| static auto | runBlocking (QProcess &process, const QString &app, const QStringList &args, const QString &input, QString *process_out, QString *process_err, const std::atomic_bool *cancel=nullptr, int timeoutMs=-1) -> int |
| | Shared blocking run: start process, optionally feed input on stdin, wait, and capture stdout/stderr. Backs the executeBlocking overloads. The caller configures process (e.g. environment) first.
|
Runs non-interactive external commands in FIFO order using a single QProcess.
Queues execution requests and emits per-request completion or error signals; supports optional stdin, configurable stdout/stderr capture, and per-request working directory and environment.
Definition at line 31 of file executor.h.
| void Executor::dequeuing |
( |
int | id, |
|
|
bool | completes ) |
|
signal |
Emitted, synchronously, when the queue's head leaves it: just before it is started, when it cannot be (no executable, a failed start), or when cancelNext() drops it. Lets a caller do per-item work at the moment the item actually runs, not when it was queued.
- Parameters
-
| id | The item's id. |
| completes | Whether finished() or error() follows for it: for every item but one cancelNext() dropped. Those that complete do so in the order they left the queue. |
A slot may queue more with execute(): that waits behind this item. The executor counts as running while the signal is out, also for an item cancelNext() drops, so cancelNext() drops nothing then (-1) and nothing starts until the signal has returned.
| void Executor::detachFromTerminal |
( |
QProcess & | process | ) |
|
|
static |
Make process start its child without a controlling terminal.
On Unix the child starts in a new session (setsid), so it has no /dev/tty. git and ssh then use an askpass helper when there is one and fail at once otherwise, instead of prompting in the terminal QtPass was started from while the queue waits behind them. Other Unix process flags set on process are kept. Does nothing on Windows. Every child QtPass starts goes through this; startProcess() calls it for the queued and the blocking path.
- Parameters
-
| process | Process to configure; call it before start(). |
Definition at line 34 of file executor.cpp.
| auto Executor::executeBlocking |
( |
QProcess & | process, |
|
|
const QString & | app, |
|
|
const QStringList & | args, |
|
|
const QString & | input = QString(), |
|
|
QString * | process_out = nullptr, |
|
|
QString * | process_err = nullptr, |
|
|
const std::atomic_bool * | cancel = nullptr, |
|
|
int | timeoutMs = -1 ) -> int |
|
staticnodiscard |
Run a command synchronously on a caller-supplied QProcess, with optional cancellation.
The caller configures process (environment, say) before the call; it must be a fresh, not yet started object. QProcess is not thread-safe, so process belongs to the calling thread for the whole run: no other thread may call terminate(), kill() or anything else on it. To let a run be cancelled, pass cancel: the wait then polls the flag, and once it is set the calling thread itself terminate()s the child, waits a short grace period, kill()s it if it is still running, waits one more grace period at most, and returns -1. Setting the flag is the only thing another thread does; it may do so at any time, before or during the run. A run given timeoutMs ends the same way once that time has passed, start included, so it returns within the timeout plus twice the grace even when a kill()ed child cannot exit yet (uninterruptible sleep on a hung mount). Not timed: QProcess::start() itself, which can block, for example opening a FIFO named by a redirected channel (no caller redirects one), and QProcess's destructor, which still waits for such a child, for up to 30 s.
- Parameters
-
| process | Process object to run the command on. |
| app | Executable path. |
| args | Command arguments. |
| input | Data to write to stdin. |
| process_out | If non-null, receives stdout output. |
| process_err | If non-null, receives stderr output. |
| cancel | If non-null, a flag that ends the run when set. |
| timeoutMs | Time for the whole run, start included; negative (the default) for none. |
- Returns
- Process exit code, or -1 if it failed to start, crashed, was cancelled or ran out of time.
Definition at line 429 of file executor.cpp.
| void Executor::executeNext |
( |
| ) |
|
|
private |
Start the head of the queue unless something runs or the queue is empty.
Marks the executor running and emits dequeuing() before touching the item, so a slot there cannot invalidate it. An item with no executable is failed with a queued error() (an empty command used to wedge the queue, #1682) and the next one is tried at once. Called after each execute() and from onProcessFinished().
Definition at line 192 of file executor.cpp.
| auto Executor::hasQueued |
( |
int | id | ) |
const -> bool |
|
inline |
Whether a command with process id id is queued or running.
The running command stays at the head of the queue until it finishes, so one scan covers both the queued and the running one. Used to refuse a store change while a Git pull is still in flight, whose conflict a call-time check could not yet see.
- Parameters
-
- Returns
- true when the queue holds a command with that id.
Definition at line 437 of file executor.h.
| void Executor::onProcessFinished |
( |
int | exitCode, |
|
|
QProcess::ExitStatus | exitStatus ) |
|
privateslot |
Finish the running item when its process exits.
Dequeues the head, collects its output and emits finished() for a normal exit or error() with exit code -1 for a crash (Qt leaves the code undefined then, and 0 or 1 would be mistaken for success or "no matches"), then starts the next item and posts a drained() check.
- Parameters
-
| exitCode | Exit code reported by QProcess. |
| exitStatus | Whether the process exited normally or crashed. |
Definition at line 478 of file executor.cpp.
| auto Executor::parseWslCommand |
( |
const QString & | app | ) |
-> std::optional< WslCommand > |
|
static |
Parse a configured executable as a WSL command.
Accepts wsl or wsl.exe in any case, bare or as a path, followed by wsl.exe options and exactly one program: wsl gpg, WSL.EXE -d Debian
/usr/bin/gpg, C:\Windows\System32\wsl.exe -u me gpg. A -e/--exec the user wrote is dropped (argv() adds it), anything after the program (wsl sh -c "gpg") or a wsl with no program is not a WSL command.
Every place that starts, probes or translates paths for a configured executable goes through this, so a form one of them accepts cannot be started differently by another.
- Parameters
-
| app | Executable as configured. |
- Returns
- The parsed command, or nothing when
app is not one.
Definition at line 114 of file executor.cpp.
| auto Executor::resolveExecutable |
( |
const QString & | app | ) |
-> QString |
|
static |
The one rule for turning a configured executable into what runs.
Absolute paths and "wsl ..." commands are used as given. A bare or relative name is looked up next to the application first (the Windows and macOS bundles ship gpg/git/pass there) and otherwise left for QProcess's PATH lookup. Both the queued and the blocking path go through this, so the same setting can no longer run two different binaries.
- Parameters
-
| app | Executable as configured. |
- Returns
- What to hand to QProcess::start().
Definition at line 86 of file executor.cpp.
| auto Executor::runBlocking |
( |
QProcess & | process, |
|
|
const QString & | app, |
|
|
const QStringList & | args, |
|
|
const QString & | input, |
|
|
QString * | process_out, |
|
|
QString * | process_err, |
|
|
const std::atomic_bool * | cancel = nullptr, |
|
|
int | timeoutMs = -1 ) -> int |
|
staticprivate |
Shared blocking run: start process, optionally feed input on stdin, wait, and capture stdout/stderr. Backs the executeBlocking overloads. The caller configures process (e.g. environment) first.
With a null cancel the wait is a plain waitForFinished(-1). With a non-null one the wait polls the flag; once it is set this thread terminate()s the child, gives it a short grace period, kill()s it if it is still running, waits one more grace period at most, and returns -1. A flag that is already set skips the start altogether.
- Parameters
-
| process | Pre-configured QProcess to run. |
| app | Executable path. |
| args | Command arguments. |
| input | Data to write to stdin (empty = none). |
| process_out | If non-null, receives stdout. |
| process_err | If non-null, receives stderr. |
| cancel | Optional flag another thread may set to end the run. |
| timeoutMs | Time for the whole run, start included; negative for none. |
- Returns
- Process exit code, or -1 on start/crash failure, cancel or timeout.
Definition at line 382 of file executor.cpp.
| void Executor::setChildUmask |
( |
int | mask | ) |
|
|
static |
The umask every child QtPass starts gets, as pass sets its own.
pass runs git and gpg under umask 077 (or PASSWORD_STORE_UMASK), so the folders and files they create in the store, .git included, are the user's alone. QtPass gives that umask to the processes it starts (startProcess(), the queue and the blocking calls) and not to itself: a browser or file manager it opens keeps the session's. Unix only.
- Parameters
-
| mask | The umask, or a negative value for none (the default). |
Definition at line 65 of file executor.cpp.