Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Marco Bubke
flatpak-qt-creator
Commits
bbaf7893
Commit
bbaf7893
authored
Feb 20, 2009
by
Oswald Buddenhagen
Browse files
"debug in terminal" feature.
includes complete refactoring of ConsoleProcess.
parent
d35e1906
Changes
14
Hide whitespace changes
Inline
Side-by-side
src/libs/libs.pro
View file @
bbaf7893
...
...
@@ -6,4 +6,5 @@ SUBDIRS = \
aggregation
\
extensionsystem
\
utils
\
utils
/
process_stub
.
pro
\
cplusplus
src/libs/utils/consoleprocess.h
View file @
bbaf7893
...
...
@@ -37,9 +37,12 @@
#include <QtCore/QStringList>
#include <QtCore/QProcess>
#include <QtNetwork/QLocalServer>
#ifdef Q_OS_WIN
#include <windows.h>
class
QWinEventNotifier
;
class
QTemporaryFile
;
#endif
namespace
Core
{
...
...
@@ -50,41 +53,68 @@ class QWORKBENCH_UTILS_EXPORT ConsoleProcess : public QObject, public AbstractPr
Q_OBJECT
public:
ConsoleProcess
(
QObject
*
parent
);
ConsoleProcess
(
QObject
*
parent
=
0
);
~
ConsoleProcess
();
bool
start
(
const
QString
&
program
,
const
QStringList
&
args
);
void
stop
();
bool
isRunning
()
const
;
qint64
applicationPID
()
const
;
int
exitCode
()
const
;
void
setDebug
(
bool
on
)
{
m_debug
=
on
;
}
bool
isDebug
()
const
{
return
m_debug
;
}
bool
isRunning
()
const
;
// This reflects the state of the console+stub
qint64
applicationPID
()
const
{
return
m_appPid
;
}
int
exitCode
()
const
{
return
m_appCode
;
}
// This will be the signal number if exitStatus == CrashExit
QProcess
::
ExitStatus
exitStatus
()
const
{
return
m_appStatus
;
}
#ifdef Q_OS_WIN
// These are public for WinGuiProcess. Should be in AbstractProcess, but it has no .cpp so far.
static
QString
createCommandline
(
const
QString
&
program
,
const
QStringList
&
args
);
static
QStringList
fixEnvironment
(
const
QStringList
&
env
);
#endif
signals:
void
processError
(
const
QString
&
error
);
// These reflect the state of the actual client process
void
processStarted
();
void
processStopped
();
private:
bool
m_isRunning
;
#ifdef Q_OS_WIN
public:
static
QString
createCommandline
(
const
QString
&
program
,
const
QStringList
&
args
);
static
QByteArray
createEnvironment
(
const
QStringList
&
env
);
// These reflect the state of the console+stub
void
wrapperStarted
();
void
wrapperStopped
();
private
slots
:
void
processDied
();
void
stubConnectionAvailable
();
void
readStubOutput
();
void
stubExited
();
#ifdef Q_OS_WIN
void
inferiorExited
();
#endif
private:
QString
stubServerListen
();
void
stubServerShutdown
();
#ifdef Q_OS_WIN
void
cleanupStub
();
void
cleanupInferior
();
#endif
bool
m_debug
;
qint64
m_appPid
;
int
m_appCode
;
QString
m_executable
;
QProcess
::
ExitStatus
m_appStatus
;
QLocalServer
m_stubServer
;
QLocalSocket
*
m_stubSocket
;
#ifdef Q_OS_WIN
PROCESS_INFORMATION
*
m_pid
;
HANDLE
m_hInferior
;
QWinEventNotifier
*
inferiorFinishedNotifier
;
QWinEventNotifier
*
processFinishedNotifier
;
QTemporaryFile
*
m_tempFile
;
#else
private:
QProcess
m_process
;
private
slots
:
void
processFinished
(
int
,
QProcess
::
ExitStatus
);
QByteArray
m_stubServerDir
;
#endif
};
...
...
src/libs/utils/consoleprocess_unix.cpp
View file @
bbaf7893
...
...
@@ -29,57 +29,78 @@
#include "consoleprocess.h"
#include <QtCore/QCoreApplication>
#include <QtCore/QTemporaryFile>
#include <QtNetwork/QLocalSocket>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
using
namespace
Core
::
Utils
;
ConsoleProcess
::
ConsoleProcess
(
QObject
*
parent
)
:
QObject
(
parent
)
{
m_isRunning
=
false
;
}
m_debug
=
false
;
m_appPid
=
0
;
m_stubSocket
=
0
;
ConsoleProcess
::~
ConsoleProcess
()
{
connect
(
&
m_stubServer
,
SIGNAL
(
newConnection
()),
SLOT
(
stubConnectionAvailable
()));
m_process
.
setProcessChannelMode
(
QProcess
::
ForwardedChannels
);
connect
(
&
m_process
,
SIGNAL
(
finished
(
int
,
QProcess
::
ExitStatus
)),
SLOT
(
stubExited
()));
}
static
QString
shellEscape
(
const
QString
&
in
)
ConsoleProcess
::~
ConsoleProcess
(
)
{
QString
out
=
in
;
out
.
replace
(
'\''
,
"'
\'
'"
);
out
.
prepend
(
'\''
);
out
.
append
(
'\''
);
return
out
;
stop
();
}
bool
ConsoleProcess
::
start
(
const
QString
&
program
,
const
QStringList
&
args
)
{
if
(
m_process
.
state
()
!=
QProcess
::
Not
Running
)
if
(
is
Running
()
)
return
false
;
QString
shellArgs
;
shellArgs
+=
QLatin1String
(
"cd "
);
shellArgs
+=
shellEscape
(
workingDirectory
());
shellArgs
+=
QLatin1Char
(
';'
);
shellArgs
+=
shellEscape
(
program
);
foreach
(
const
QString
&
arg
,
args
)
{
shellArgs
+=
QLatin1Char
(
' '
);
shellArgs
+=
shellEscape
(
arg
);
}
shellArgs
+=
QLatin1String
(
"; echo; echo
\"
Press enter to close this window
\"
; read DUMMY"
);
m_process
.
setEnvironment
(
environment
());
QString
err
=
stubServerListen
();
if
(
!
err
.
isEmpty
())
{
emit
processError
(
tr
(
"Cannot set up comm channel: %1"
).
arg
(
err
));
return
false
;
}
connect
(
&
m_process
,
SIGNAL
(
finished
(
int
,
QProcess
::
ExitStatus
)),
this
,
SLOT
(
processFinished
(
int
,
QProcess
::
ExitStatus
)));
QStringList
xtermArgs
;
xtermArgs
<<
"-e"
<<
(
QCoreApplication
::
applicationDirPath
()
+
"/qtcreator_process_stub"
)
<<
(
m_debug
?
"debug"
:
"exec"
)
<<
m_stubServer
.
fullServerName
()
<<
tr
(
"Press <RETURN> to close this window..."
)
<<
workingDirectory
()
<<
environment
()
<<
""
<<
program
<<
args
;
m_process
.
start
(
QLatin1String
(
"xterm"
),
QStringList
()
<<
QLatin1String
(
"-e"
)
<<
"/bin/sh"
<<
"-c"
<<
shellArgs
);
if
(
!
m_process
.
waitForStarted
())
m_process
.
start
(
QLatin1String
(
"xterm"
),
xtermArgs
);
if
(
!
m_process
.
waitForStarted
())
{
stubServerShutdown
();
emit
processError
(
tr
(
"Cannot start console emulator xterm."
));
return
false
;
emit
processStarted
();
}
m_executable
=
program
;
emit
wrapperStarted
();
return
true
;
}
void
ConsoleProcess
::
processFinished
(
int
,
QProcess
::
ExitStatus
)
void
ConsoleProcess
::
stop
(
)
{
emit
processStopped
();
if
(
!
isRunning
())
return
;
stubServerShutdown
();
m_appPid
=
0
;
m_process
.
terminate
();
if
(
!
m_process
.
waitForFinished
(
1000
))
m_process
.
kill
();
m_process
.
waitForFinished
();
}
bool
ConsoleProcess
::
isRunning
()
const
...
...
@@ -87,19 +108,97 @@ bool ConsoleProcess::isRunning() const
return
m_process
.
state
()
!=
QProcess
::
NotRunning
;
}
void
ConsoleProcess
::
st
op
()
QString
ConsoleProcess
::
st
ubServerListen
()
{
m_process
.
terminate
();
m_process
.
waitForFinished
();
// We need to put the socket in a private directory, as some systems simply do not
// check the file permissions of sockets.
QString
stubFifoDir
;
forever
{
{
QTemporaryFile
tf
;
if
(
!
tf
.
open
())
return
tr
(
"Cannot create temporary file: %2"
).
arg
(
tf
.
errorString
());
stubFifoDir
=
QFile
::
encodeName
(
tf
.
fileName
());
}
// By now the temp file was deleted again
m_stubServerDir
=
QFile
::
encodeName
(
stubFifoDir
);
if
(
!::
mkdir
(
m_stubServerDir
.
constData
(),
0700
))
break
;
if
(
errno
!=
EEXIST
)
return
tr
(
"Cannot create temporary directory %1: %2"
).
arg
(
stubFifoDir
,
strerror
(
errno
));
}
QString
stubServer
=
stubFifoDir
+
"/stub-socket"
;
if
(
!
m_stubServer
.
listen
(
stubServer
))
{
::
rmdir
(
m_stubServerDir
.
constData
());
return
tr
(
"Cannot create socket %1: %2"
).
arg
(
stubServer
,
m_stubServer
.
errorString
());
}
return
QString
();
}
void
ConsoleProcess
::
stubServerShutdown
()
{
delete
m_stubSocket
;
m_stubSocket
=
0
;
if
(
m_stubServer
.
isListening
())
{
m_stubServer
.
close
();
::
rmdir
(
m_stubServerDir
.
constData
());
}
}
void
ConsoleProcess
::
stubConnectionAvailable
()
{
m_stubSocket
=
m_stubServer
.
nextPendingConnection
();
connect
(
m_stubSocket
,
SIGNAL
(
readyRead
()),
SLOT
(
readStubOutput
()));
}
qint64
ConsoleProcess
::
applicationPID
()
const
static
QString
errorMsg
(
int
code
)
{
return
m_process
.
pid
(
);
return
QString
::
fromLocal8Bit
(
strerror
(
code
)
);
}
int
ConsoleProcess
::
exitCode
()
const
void
ConsoleProcess
::
readStubOutput
()
{
return
m_process
.
exitCode
();
while
(
m_stubSocket
->
canReadLine
())
{
QByteArray
out
=
m_stubSocket
->
readLine
();
out
.
chop
(
1
);
// \n
if
(
out
.
startsWith
(
"err:chdir "
))
{
emit
processError
(
tr
(
"Cannot change to working directory %1: %2"
)
.
arg
(
workingDirectory
(),
errorMsg
(
out
.
mid
(
10
).
toInt
())));
}
else
if
(
out
.
startsWith
(
"err:exec "
))
{
emit
processError
(
tr
(
"Cannot execute %1: %2"
)
.
arg
(
m_executable
,
errorMsg
(
out
.
mid
(
9
).
toInt
())));
}
else
if
(
out
.
startsWith
(
"pid "
))
{
m_appPid
=
out
.
mid
(
4
).
toInt
();
emit
processStarted
();
}
else
if
(
out
.
startsWith
(
"exit "
))
{
m_appStatus
=
QProcess
::
NormalExit
;
m_appCode
=
out
.
mid
(
5
).
toInt
();
m_appPid
=
0
;
emit
processStopped
();
}
else
if
(
out
.
startsWith
(
"crash "
))
{
m_appStatus
=
QProcess
::
CrashExit
;
m_appCode
=
out
.
mid
(
6
).
toInt
();
m_appPid
=
0
;
emit
processStopped
();
}
else
{
emit
processError
(
tr
(
"Unexpected output from helper program."
));
m_process
.
terminate
();
break
;
}
}
}
void
ConsoleProcess
::
stubExited
()
{
// The stub exit might get noticed before we read the error status.
if
(
m_stubSocket
&&
m_stubSocket
->
state
()
==
QLocalSocket
::
ConnectedState
)
m_stubSocket
->
waitForDisconnected
();
stubServerShutdown
();
if
(
m_appPid
)
{
m_appStatus
=
QProcess
::
CrashExit
;
m_appCode
=
-
1
;
m_appPid
=
0
;
emit
processStopped
();
// Maybe it actually did not, but keep state consistent
}
emit
wrapperStopped
();
}
src/libs/utils/consoleprocess_win.cpp
View file @
bbaf7893
...
...
@@ -29,19 +29,31 @@
#include "consoleprocess.h"
#include <QtCore/QCoreApplication>
#include <QtCore/QDir>
#include <QtCore/
private/qwineventnotifier_p.h
>
#include <QtCore/
QTemporaryFile
>
#include <QtCore/QAbstractEventDispatcher>
#include <QtCore/private/qwineventnotifier_p.h>
#include <QtNetwork/QLocalSocket>
#include <
Tlhelp32
.h>
#include <
stdlib
.h>
using
namespace
Core
::
Utils
;
ConsoleProcess
::
ConsoleProcess
(
QObject
*
parent
)
:
QObject
(
parent
)
{
m_isRunning
=
false
;
m_debug
=
false
;
m_appPid
=
0
;
m_pid
=
0
;
m_hInferior
=
NULL
;
m_tempFile
=
0
;
m_stubSocket
=
0
;
processFinishedNotifier
=
0
;
inferiorFinishedNotifier
=
0
;
connect
(
&
m_stubServer
,
SIGNAL
(
newConnection
()),
SLOT
(
stubConnectionAvailable
()));
}
ConsoleProcess
::~
ConsoleProcess
()
...
...
@@ -49,156 +61,234 @@ ConsoleProcess::~ConsoleProcess()
stop
();
}
void
ConsoleProcess
::
stop
()
{
if
(
m_pid
)
TerminateProcess
(
m_pid
->
hProcess
,
-
1
);
m_isRunning
=
false
;
}
bool
ConsoleProcess
::
start
(
const
QString
&
program
,
const
QStringList
&
args
)
{
if
(
m_
isRunning
)
if
(
isRunning
()
)
return
false
;
QString
err
=
stubServerListen
();
if
(
!
err
.
isEmpty
())
{
emit
processError
(
tr
(
"Cannot set up comm channel: %1"
).
arg
(
err
));
return
false
;
}
if
(
!
environment
().
isEmpty
())
{
m_tempFile
=
new
QTemporaryFile
();
if
(
!
m_tempFile
->
open
())
{
stubServerShutdown
();
emit
processError
(
tr
(
"Cannot create temp file: %1"
).
arg
(
m_tempFile
->
errorString
()));
delete
m_tempFile
;
m_tempFile
=
0
;
return
false
;
}
QTextStream
out
(
m_tempFile
);
out
.
setCodec
(
"UTF-16LE"
);
out
.
setGenerateByteOrderMark
(
false
);
foreach
(
const
QString
&
var
,
fixEnvironment
(
environment
()))
out
<<
var
<<
QChar
(
0
);
out
<<
QChar
(
0
);
}
STARTUPINFO
si
;
ZeroMemory
(
&
si
,
sizeof
(
si
));
si
.
cb
=
sizeof
(
si
);
if
(
m_pid
)
{
CloseHandle
(
m_pid
->
hThread
);
CloseHandle
(
m_pid
->
hProcess
);
delete
m_pid
;
m_pid
=
0
;
}
m_pid
=
new
PROCESS_INFORMATION
;
ZeroMemory
(
m_pid
,
sizeof
(
PROCESS_INFORMATION
));
QString
cmdLine
=
QLatin1String
(
"cmd /k "
)
+
createCommandline
(
program
,
args
)
+
QLatin1String
(
" & pause & exit"
);
QString
workDir
=
QDir
::
toNativeSeparators
(
workingDirectory
());
if
(
!
workDir
.
isEmpty
()
&&
!
workDir
.
endsWith
(
'\\'
))
workDir
.
append
(
'\\'
);
QStringList
stubArgs
;
stubArgs
<<
(
m_debug
?
"debug"
:
"exec"
)
<<
m_stubServer
.
fullServerName
()
<<
workDir
<<
(
m_tempFile
?
m_tempFile
->
fileName
()
:
0
)
<<
createCommandline
(
program
,
args
)
<<
tr
(
"Press <RETURN> to close this window..."
);
QString
cmdLine
=
createCommandline
(
QCoreApplication
::
applicationDirPath
()
+
"/qtcreator_process_stub.exe"
,
stubArgs
);
bool
success
=
CreateProcessW
(
0
,
(
WCHAR
*
)
cmdLine
.
utf16
(),
0
,
0
,
TRUE
,
CREATE_NEW_CONSOLE
|
CREATE_UNICODE_ENVIRONMENT
,
environment
().
isEmpty
()
?
0
:
createEnvironment
(
environment
()).
data
(),
workingDirectory
().
isEmpty
()
?
0
:
(
WCHAR
*
)
QDir
::
convertSeparators
(
workingDirectory
()).
utf16
(),
0
,
0
,
FALSE
,
CREATE_NEW_CONSOLE
,
0
,
0
,
&
si
,
m_pid
);
if
(
!
success
)
{
delete
m_pid
;
m_pid
=
0
;
delete
m_tempFile
;
m_tempFile
=
0
;
stubServerShutdown
();
emit
processError
(
tr
(
"The process could not be started!"
));
return
false
;
}
if
(
QAbstractEventDispatcher
::
instance
(
thread
()))
{
processFinishedNotifier
=
new
QWinEventNotifier
(
m_pid
->
hProcess
,
this
);
QObject
::
connect
(
processFinishedNotifier
,
SIGNAL
(
activated
(
HANDLE
)),
this
,
SLOT
(
processDied
()));
processFinishedNotifier
->
setEnabled
(
true
);
processFinishedNotifier
=
new
QWinEventNotifier
(
m_pid
->
hProcess
,
this
);
connect
(
processFinishedNotifier
,
SIGNAL
(
activated
(
HANDLE
)),
SLOT
(
stubExited
()));
emit
wrapperStarted
();
return
true
;
}
void
ConsoleProcess
::
stop
()
{
if
(
m_hInferior
!=
NULL
)
{
TerminateProcess
(
m_hInferior
,
(
unsigned
)
-
1
);
cleanupInferior
();
}
if
(
m_pid
)
{
TerminateProcess
(
m_pid
->
hProcess
,
(
unsigned
)
-
1
);
WaitForSingleObject
(
m_pid
->
hProcess
,
INFINITE
);
cleanupStub
();
}
m_isRunning
=
true
;
emit
processStarted
();
return
success
;
}
bool
ConsoleProcess
::
isRunning
()
const
{
return
m_
isRunning
;
return
m_
pid
!=
0
;
}
void
ConsoleProcess
::
processDied
()
QString
ConsoleProcess
::
stubServerListen
()
{
if
(
processFinishedNotifier
)
{
processFinishedNotifier
->
setEnabled
(
false
);
delete
processFinishedNotifier
;
processFinishedNotifier
=
0
;
}
delete
m_pid
;
m_pid
=
0
;
m_isRunning
=
false
;
emit
processStopped
();
if
(
m_stubServer
.
listen
(
QString
::
fromLatin1
(
"creator-%1-%2"
)
.
arg
(
QCoreApplication
::
applicationPid
())
.
arg
(
rand
())))
return
QString
();
return
m_stubServer
.
errorString
();
}
qint64
ConsoleProcess
::
applicationPID
()
const
void
ConsoleProcess
::
stubServerShutdown
()
{
if
(
m_pid
)
{
HANDLE
hProcList
=
CreateToolhelp32Snapshot
(
TH32CS_SNAPPROCESS
,
0
);
PROCESSENTRY32
procEntry
;
procEntry
.
dwSize
=
sizeof
(
PROCESSENTRY32
);
DWORD
procId
=
0
;
BOOL
moreProc
=
Process32First
(
hProcList
,
&
procEntry
);
while
(
moreProc
)
{
if
(
procEntry
.
th32ParentProcessID
==
m_pid
->
dwProcessId
)
{
procId
=
procEntry
.
th32ProcessID
;
break
;
}
moreProc
=
Process32Next
(
hProcList
,
&
procEntry
);
}
delete
m_stubSocket
;
m_stubSocket
=
0
;
if
(
m_stubServer
.
isListening
())
m_stubServer
.
close
();
}
CloseHandle
(
hProcList
);
return
procId
;
}
return
0
;
void
ConsoleProcess
::
stubConnectionAvailable
()
{
m_stubSocket
=
m_stubServer
.
nextPendingConnection
();
connect
(
m_stubSocket
,
SIGNAL
(
readyRead
()),
SLOT
(
readStubOutput
()))
;
}
int
ConsoleProcess
::
exitCode
()
const
static
QString
errorMsg
(
int
code
)
{
DWORD
exitCode
;
if
(
GetExitCodeProcess
(
m_pid
->
hProcess
,
&
exitCode
))
return
exitCode
;
return
-
1
;
LPVOID
lpMsgBuf
;
int
len
=
FormatMessage
(
FORMAT_MESSAGE_ALLOCATE_BUFFER
|
FORMAT_MESSAGE_FROM_SYSTEM
|
FORMAT_MESSAGE_IGNORE_INSERTS
,
NULL
,
(
DWORD
)
code
,
0
,
(
LPTSTR
)
&
lpMsgBuf
,
0
,
NULL
);
QString
ret
=
QString
::
fromUtf16
((
ushort
*
)
lpMsgBuf
,
len
);
LocalFree
(
lpMsgBuf
);
return
ret
;
}
QByteArray
ConsoleProcess
::
c
rea
teEnvironment
(
const
QStringList
&
env
)
void
ConsoleProcess
::
rea
dStubOutput
(
)
{
QByteArray
envlist
;
if
(
!
env
.
isEmpty
())
{
QStringList
envStrings
=
env
;
int
pos
=
0
;
// add PATH if necessary (for DLL loading)
if
(
envStrings
.
filter
(
QRegExp
(
"^PATH="
,
Qt
::
CaseInsensitive
)).
isEmpty
())
{
QByteArray
path
=
qgetenv
(
"PATH"
);
if
(
!
path
.
isEmpty
())
envStrings
.
prepend
(
QString
(
QLatin1String
(
"PATH=%1"
)).
arg
(
QString
::
fromLocal8Bit
(
path
)));
}
// add systemroot if needed
if
(
envStrings
.
filter
(
QRegExp
(
"^SystemRoot="
,
Qt
::
CaseInsensitive
)).
isEmpty
())
{
QByteArray
systemRoot
=
qgetenv
(
"SystemRoot"
);
if
(
!
systemRoot
.
isEmpty
())
envStrings
.
prepend
(
QString
(
QLatin1String
(
"SystemRoot=%1"
)).
arg
(
QString
::
fromLocal8Bit
(
systemRoot
)));
}
#ifdef UNICODE
if
(
!
(
QSysInfo
::
WindowsVersion
&
QSysInfo
::
WV_DOS_based
))
{
for
(
QStringList
::
ConstIterator
it
=
envStrings
.
constBegin
();
it
!=
envStrings
.
constEnd
();
it
++
)
{
QString
tmp
=
*
it
;
uint
tmpSize
=
sizeof
(
TCHAR
)
*
(
tmp
.
length
()
+
1
);
envlist
.
resize
(
envlist
.
size
()
+
tmpSize
);
memcpy
(
envlist
.
data
()
+
pos
,
tmp
.
utf16
(),
tmpSize
);
pos
+=
tmpSize
;
}
// add the 2 terminating 0 (actually 4, just to be on the safe side)
envlist
.
resize
(
envlist
.
size
()
+
4
);
envlist
[
pos
++
]
=
0
;
envlist
[
pos
++
]
=
0
;
envlist
[
pos
++
]
=
0
;
envlist
[
pos
++
]
=
0
;
}
else
#endif // UNICODE
{
for
(
QStringList
::
ConstIterator
it
=
envStrings
.
constBegin
();
it
!=
envStrings
.
constEnd
();
it
++
)
{
QByteArray
tmp
=
(
*
it
).
toLocal8Bit
();
uint
tmpSize
=
tmp
.
length
()
+
1
;
envlist
.
resize
(
envlist
.
size
()
+
tmpSize
);
memcpy
(
envlist
.
data
()
+
pos
,
tmp
.
data
(),
tmpSize
);
pos
+=
tmpSize
;
while
(
m_stubSocket
->
canReadLine
())
{
QByteArray
out
=
m_stubSocket
->
readLine
();
out
.
chop
(
2
);
// \r\n
if
(
out
.
startsWith
(
"err:chdir "
))
{
emit
processError
(
tr
(
"Cannot change to working directory %1: %2"
)
.
arg
(
workingDirectory
(),
errorMsg
(
out
.
mid
(
10
).
toInt
())));
}
else
if
(
out
.
startsWith
(
"err:exec "
))
{
emit
processError
(
tr
(
"Cannot execute %1: %2"
)
.
arg
(
m_executable
,
errorMsg
(
out
.
mid
(
9
).
toInt
())));
}
else
if
(
out
.
startsWith
(
"pid "
))
{
// Will not need it any more
delete
m_tempFile
;