summaryrefslogtreecommitdiffstats
path: root/src/processmanager/qprocessfrontend.cpp
blob: 7c1cbb6f71d796c0fdc1d649a1c88e2a51c7242b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "qprocessfrontend.h"
#include "qprocessbackend.h"

#include <QDateTime>

/***************************************************************************************/

QT_BEGIN_NAMESPACE_PROCESSMANAGER

/*!
    \class QProcessFrontend
    \brief The QProcessFrontend class is a generalized representation of a process.
    \inmodule QtProcessManager

    The QProcessFrontend class encapsulates a process whose lifecycle is controlled by the process manager.
    It is a generalized representation - in actuality, subclasses of the QProcessFrontend class are used
    to control processes.  These subclasses are used to accelerate process launching, wrap
    processes with additional arguments and settings, or fake the existence of a process.
    The QProcessFrontend class itself cannot be instantiated.

    A process object always contains a ProcessInfo object, which is the static information
    used to start and execute the process.
*/

/*!
    \property QProcessFrontend::identifier
    \brief the application identifier of the process.
*/

/*!
    \property QProcessFrontend::name
    \brief the application name of the process.
*/

/*!
    \property QProcessFrontend::program
    \brief the filename of the binary executable that is launched to start up the process.
*/

/*!
    \property QProcessFrontend::arguments
    \brief the arguments that will be passed to the program upon process startup
*/

/*!
    \property QProcessFrontend::environment
    \brief a map of the environment variables that will be used by the process
*/

/*!
    \property QProcessFrontend::workingDirectory
    \brief the directory that will be switched to before launching the process
*/

/*!
    \property QProcessFrontend::pid
    \brief the process id (PID) of the process.

    Returns 0 if the process has not been started or if this is a "fake" process.
*/

/*!
    \property QProcessFrontend::startTime
    \brief the start time of the process, measured in milliseconds since the epoch (1st Jan 1970 00:00).

    Returns 0 if process has not been started.
*/

/*!
    \property QProcessFrontend::priority
    \brief The Unix process priority (niceness).

    Returns the current process priority if the process is running.  Otherwise,
    it returns the QProcessFrontend priority setting.  You can only set the priority once the
    process is running.
*/

/*!
    \property QProcessFrontend::oomAdjustment
    \brief The Unix process /proc/<pid>/oom_score_adj (likelihood of being killed)

    Returns the current OOM adjustment score if the process is running.  Otherwise,
    it returns the QProcessFrontend OOM adjustment score setting.  You can only set the OOM adjustment
    score when the process is running.
*/

/*!
    \property QProcessFrontend::errorString
    \brief The human-readable string describing the last error.

    Returns the string describing the last error received.  This is equivalent to
    the string passed by the error() signal.
*/

/*!
    \internal
    Constructs a QProcessFrontend instance with QProcessBackend \a process and optional \a parent
    The QProcessFrontend takes ownership of the QProcessBackend.
*/
QProcessFrontend::QProcessFrontend(QProcessBackend *backend, QObject *parent)
    : QObject(parent)
    , m_startTimeSinceEpoch(0)
    , m_backend(backend)
{
    Q_ASSERT(backend);
    backend->setParent(this);
    connect(backend, SIGNAL(started()), SLOT(handleStarted()));
    connect(backend, SIGNAL(error(QProcess::ProcessError)), SLOT(handleError(QProcess::ProcessError)));
    connect(backend, SIGNAL(finished(int, QProcess::ExitStatus)),
            SLOT(handleFinished(int, QProcess::ExitStatus)));
    connect(backend, SIGNAL(stateChanged(QProcess::ProcessState)),
            SLOT(handleStateChanged(QProcess::ProcessState)));
    connect(backend, SIGNAL(standardOutput(const QByteArray&)),
            SLOT(handleStandardOutput(const QByteArray&)));
    connect(backend, SIGNAL(standardError(const QByteArray&)),
            SLOT(handleStandardError(const QByteArray&)));
}

/*!
  Destroy this process object.
*/

QProcessFrontend::~QProcessFrontend()
{
}

/*!
    Return the process identifier
*/

QString QProcessFrontend::identifier() const
{
    Q_ASSERT(m_backend);
    return m_backend->identifier();
}

/*!
    Return the process name
*/

QString QProcessFrontend::name() const
{
    Q_ASSERT(m_backend);
    return m_backend->name();
}

/*!
    Return the process program
*/

QString QProcessFrontend::program() const
{
    Q_ASSERT(m_backend);
    return m_backend->program();
}

/*!
    Return the process arguments
*/

QStringList QProcessFrontend::arguments() const
{
    Q_ASSERT(m_backend);
    return m_backend->arguments();
}

/*!
    Return the process environment
*/

QVariantMap QProcessFrontend::environment() const
{
    Q_ASSERT(m_backend);
    return m_backend->environment();
}

/*!
    Return the process working directory
*/

QString QProcessFrontend::workingDirectory() const
{
    Q_ASSERT(m_backend);
    return m_backend->workingDirectory();
}

/*!
    Returns the PID of this process. If the process has not started up yet properly, its PID will be 0.
*/
Q_PID QProcessFrontend::pid() const
{
    Q_ASSERT(m_backend);
    return m_backend->pid();
}

/*!
  Return the current process priority.
  This may be different than the desired process priority.
*/

qint32 QProcessFrontend::priority() const
{
    Q_ASSERT(m_backend);
    return m_backend->actualPriority();
}

/*!
    Set the process priority
*/

void QProcessFrontend::setPriority(qint32 priority)
{
    Q_ASSERT(m_backend);
    if (priority != m_backend->desiredPriority()) {
        m_backend->setDesiredPriority(priority);
        emit priorityChanged();
    }
}

/*!
    Return the process actual oomAdjustment
*/

qint32 QProcessFrontend::oomAdjustment() const
{
    Q_ASSERT(m_backend);
    return m_backend->actualOomAdjustment();
}

/*!
    Set the process desired oomAdjustment.
    This may be different than the actual process oomAdjustment
*/

void QProcessFrontend::setOomAdjustment(qint32 oomAdjustment)
{
    Q_ASSERT(m_backend);
    if (oomAdjustment != m_backend->desiredOomAdjustment()) {
        m_backend->setDesiredOomAdjustment(oomAdjustment);
        emit oomAdjustmentChanged();
    }
}

/*!
    Returns the state of the process.
    The base class always returns NotRunning.
*/
QProcess::ProcessState QProcessFrontend::state() const
{
    Q_ASSERT(m_backend);
    return m_backend->state();
}

/*!
    \brief Starts the process.

    After the process is started, the started() signal is emitted.
    If a process fails to start (e.g. because it doesn't give any output until timeout) then
    the (partly) started process is killed and error() is emitted.

    This function must be overridden in subclasses.

    \sa started()
    \sa error()
*/
void QProcessFrontend::start()
{
    if (state() == QProcess::NotRunning) {
        Q_ASSERT(m_backend);
        emit aboutToStart();
        m_startTimeSinceEpoch = QDateTime::currentMSecsSinceEpoch();
        m_backend->start();
    }
}

/*!
    Attempts to stop a process by giving it a \a timeout time to die, measured in milliseconds.

    If the process does not die in the given time limit, it is killed.

    \sa finished()
*/
void QProcessFrontend::stop(int timeout)
{
    Q_ASSERT(m_backend);
    emit aboutToStop();
    m_backend->stop(timeout);
}

/*!
  Writes at most \a maxSize bytes of data from \a data to the process.
  Returns the number of bytes that were actually written, or -1 if an error occurred.
 */

qint64 QProcessFrontend::write(const char *data, qint64 maxSize)
{
    return m_backend->write(data, maxSize);
}

/*!
  Writes \a data from a zero-terminated string of 8-bit characters to the process.
  Returns the number of bytes that were actually written, or -1 if an error occurred.
  This is equivalent to

\code
  QProcessFrontend::write(data, qstrlen(data));
\endcode
 */

qint64 QProcessFrontend::write(const char *data)
{
    return m_backend->write(data, qstrlen(data));
}

/*!
  Writes the content of \a byteArray to the process.
  Returns the number of bytes that were actually written, or -1 if an error occurred.
 */

qint64 QProcessFrontend::write(const QByteArray& byteArray)
{
    return m_backend->write(byteArray.data(), byteArray.length());
}

/*!
    Returns the start time of the process, measured in milliseconds since the epoch (1st Jan 1970 00:00).
*/
qint64 QProcessFrontend::startTime() const
{
    return m_startTimeSinceEpoch;
}

/*!
    Returns the ProcessInfo object as a QVariantMap.

    If you use this method to retrieve the ProcessInfo content from the C++ side, you can
    wrap it around QProcessInfo() object for convenience.
*/
QVariantMap QProcessFrontend::processInfo() const
{
    return m_backend->processInfo().toMap();
}

/*!
  Handle a started() signal from the backend.
  The default implementation emits the started() signal.
 */
void QProcessFrontend::handleStarted()
{
    emit started();
}

/*!
  Handle an error() signal from the backend with \a processError.
  The default implementation emits the error signal.
 */
void QProcessFrontend::handleError(QProcess::ProcessError processError)
{
    emit error(processError);
}

/*!
  Handle a finished() signal from the backend with \a exitCode and \a exitStatus.
  The default implementation emits the finished() signal
 */
void QProcessFrontend::handleFinished(int exitCode, QProcess::ExitStatus exitStatus)
{
    emit finished(exitCode, exitStatus);
}

/*!
  Handle a stateChange() signal from the backend with \a state.
  The default implementation emits the stateChanged() signal
 */
void QProcessFrontend::handleStateChanged(QProcess::ProcessState state)
{
    emit stateChanged(state);
}

/*!
  Handle stdout \a data received from the process.
 */
void QProcessFrontend::handleStandardOutput(const QByteArray& data)
{
    emit standardOutput(data);
}

/*!
  Handle stderr \a data received from the process.
 */
void QProcessFrontend::handleStandardError(const QByteArray& data)
{
    emit standardError(data);
}

/*!
    Returns the backend object for this process.
*/
QProcessBackend *QProcessFrontend::backend() const
{
    return m_backend;
}


/*!
    \fn void QProcessFrontend::aboutToStart()
    This signal is emitted by start() just before the process starts running.
*/

/*!
    \fn void QProcessFrontend::aboutToStop()
    This signal is emitted by stop() just before the process is stopped.
*/

/*!
    \fn void QProcessFrontend::started()
    This signal is emitted when the process has started successfully.
*/

/*!
    \fn void QProcessFrontend::error(QProcess::ProcessError error)
    This signal is emitted when the process has failed to start or has another \a error.
*/

/*!
    \fn void QProcessFrontend::finished(int exitCode, QProcess::ExitStatus exitStatus)
    This signal is emitted when the process has stopped and its execution is over.
    The \a exitStatus tells you how the process exited; the \a exitCode is the
    return value of the process.

    Please note:  The \a exitStatus will be QProcess::CrashExit only if the
    ProcessManager stops the process externally.  A normal process that crashes
    will have an \a exitStatus of QProcess::NormalExit with a non-zero \a exitCode.
*/

/*!
    \fn void QProcessFrontend::stateChanged(QProcess::ProcessState newState)
    This signal is emitted whenever the state of QProcess changes.  The \a newState argument
    is the state the internal QProcess changed to.
*/

/*!
    \fn void QProcessFrontend::standardOutput(const QByteArray& data)
    This signal is emitted whenever \a data is received from the stdout of the process.
*/

/*!
    \fn void QProcessFrontend::standardError(const QByteArray& data)
    This signal is emitted whenever \a data is received from the stderr of the process.
*/

/*!
    \fn void QProcessFrontend::priorityChanged()
    This signal is emitted when the process priority has been changed for a running process.
*/

/*!
    \fn void QProcessFrontend::oomAdjustmentChanged()
    This signal is emitted when the process oomAdjustment has been changed for a running process.
    Only applicable under Linux.
*/

/*!
    Returns a human-readable description of the last device error that
    occurred.
 */
QString QProcessFrontend::errorString() const
{
    return m_backend->errorString();
}

#include "moc_qprocessfrontend.cpp"

QT_END_NAMESPACE_PROCESSMANAGER