File failed to load: https://isis.astrogeology.usgs.gov/9.0.0/Object/assets/jax/output/NativeMML/config.js
Isis 3 Programmer Reference
ProgramLauncher.cpp
1
5
6/* SPDX-License-Identifier: CC0-1.0 */
7#include "ProgramLauncher.h"
8
9#include <iostream>
10#include <sstream>
11#include <sys/wait.h>
12
13#include <QLocalServer>
14#include <QLocalSocket>
15#include <QProcess>
16
17#include "Application.h"
18#include "FileName.h"
19#include "IException.h"
20#include "IString.h"
21#include "Preference.h"
22
23using namespace std;
24namespace Isis {
37 void ProgramLauncher::RunIsisProgram(QString programName,
38 QString parameters) {
39 FileName program(programName);
40 FileName isisExecutableFileName("$ISISROOT/bin/" + program.name());
41 bool isIsisProgram = false;
42
43 if(isisExecutableFileName.fileExists()) {
44 isIsisProgram = true;
45 program = isisExecutableFileName;
46 }
47
48 PvlGroup &dataDir = Preference::Preferences().findGroup("DataDirectory");
49 QString tempDir = dataDir["Temporary"];
50
51 QString command = program.expanded() + " " + parameters +
52 " -pid=" + toString(getpid());
53 QStringList split = QProcess::splitCommand(command);
54 QString app = split.takeFirst();
55 QStringList paramList = split;
56
57 if(!isIsisProgram) {
58 QString msg = "Program [" + programName + "] does not appear to be a "
59 "valid Isis program";
60 throw IException(IException::Unknown, msg, _FILEINFO_);
61 }
62
63 QString serverName = "isis_" + Application::UserName() +
64 "_" + toString(getpid());
65
66 QLocalServer server;
67 server.listen(serverName);
68
69 QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
70 env.insert("TEMPORARY", tempDir);
71
72 QProcess childProcess;
73 childProcess.setProcessEnvironment(env);
74 childProcess.setProcessChannelMode(QProcess::ForwardedChannels);
75 childProcess.start(app, paramList);
76 childProcess.waitForStarted();
77
78 bool connected = false;
79
80 while(!connected && childProcess.state() != QProcess::NotRunning) {
81 // Give time for the process to connect to us or for it to finish
82 // wait 30s for the new connection....
83 connected = server.waitForNewConnection(30000);
84 childProcess.waitForFinished(100);
85 }
86
87 if(!connected) {
88 QString msg = "Isis child process failed to communicate with parent";
89 throw IException(IException::Programmer, msg, _FILEINFO_);
90 }
91
92 QLocalSocket *childSocket = server.nextPendingConnection();
93 IException errors;
94
95 // Don't return until we're done running this program
96 while(childSocket->state() != QLocalSocket::UnconnectedState) {
97 bool insideCode = true;
98 bool messageDone = false;
99
100 QString code;
101 QString message;
102 QByteArray lineData;
103
104 if(childSocket->waitForReadyRead(1000)) {
105 lineData = childSocket->read(childSocket->bytesAvailable());
106
107 for(int i = 0; i < lineData.size(); i++) {
108 if(insideCode) {
109 if(lineData[i] != (char)27) {
110 code += lineData[i];
111 }
112 else {
113 insideCode = false;
114 }
115 }
116 else {
117 if(lineData[i] != (char)27) {
118 message += lineData[i];
119 }
120 else {
121 messageDone = true;
122 insideCode = true;
123 i ++; // skip \n that should always exist here
124 }
125 }
126
127 if(messageDone) {
128 errors.append(
129 ProcessIsisMessageFromChild(code, message));
130 code = "";
131 message = "";
132 messageDone = false;
133 }
134 }
135 }
136 }
137
138 childProcess.waitForFinished();
139
140 if(childProcess.exitCode() != 0) {
141 QString msg = "Running Isis program [" + programName + "] failed with "
142 "return status [" + toString(childProcess.exitCode()) + "]";
143 throw IException(errors, IException::Unknown, msg, _FILEINFO_);
144 }
145 }
146
147
160 IException errors;
161
162 if(code == "PROGRESSTEXT" && iApp) {
163 iApp->UpdateProgress(msg, true);
164 }
165 else if(code == "PROGRESS" && iApp) {
166 iApp->UpdateProgress(toInt(msg), true);
167 }
168 else if(code == "LOG" && iApp) {
169 stringstream msgStream;
170 msgStream << msg;
171 Pvl logPvl;
172 msgStream >> logPvl;
173
174 if(logPvl.groups() == 1 &&
175 logPvl.keywords() == 0 &&
176 logPvl.objects() == 0) {
177 iApp->Log(logPvl.group(0));
178 }
179 }
180 else if(code == "GUILOG" && iApp) {
181 iApp->GuiLog(msg);
182 }
183 else if(code == "ERROR") {
184 stringstream msgStream;
185 msgStream << msg;
186 Pvl errorPvl;
187 msgStream >> errorPvl;
188
189 for(int i = 0; i < errorPvl.groups(); i++) {
190 PvlGroup &g = errorPvl.group(i);
191 QString emsg = g["Message"];
192 int ecode = g["Code"];
193 QString efile = g["File"];
194 int eline = g["Line"];
195
196 errors.append(
197 IException((IException::ErrorType)ecode, emsg, efile.toLatin1().data(), eline));
198 }
199 }
200
201 return errors;
202 }
203
204
216 void ProgramLauncher::RunSystemCommand(QString fullCommand) {
217 int status = system(fullCommand.toLatin1().data());
218
219 if(status != 0) {
220 QString msg = "Executing command [" + fullCommand +
221 "] failed with return status [" + toString(status) + "]";
222 throw IException(IException::Programmer, msg, _FILEINFO_);
223 }
224 }
225} //end namespace isis
static QString UserName()
Returns the user name.
File name manipulation and expansion.
Definition FileName.h:100
bool fileExists() const
Returns true if the file exists; false otherwise.
Definition FileName.cpp:449
QString name() const
Returns the name of the file excluding the path and the attributes in the file name.
Definition FileName.cpp:162
QString expanded() const
Returns a QString of the full file name including the file path, excluding the attributes.
Definition FileName.cpp:196
Isis exception class.
Definition IException.h:91
ErrorType
Contains a set of exception error types.
Definition IException.h:111
@ Unknown
A type of error that cannot be classified as any of the other error types.
Definition IException.h:118
@ Programmer
This error is for when a programmer made an API call that was illegal.
Definition IException.h:146
void append(const IException &exceptionSource)
Appends the given exception (and its list of previous exceptions) to this exception's causational exc...
static void RunIsisProgram(QString isisProgramName, QString arguments)
Executes the Isis program with the given arguments.
static void RunSystemCommand(QString commandLine)
This runs arbitrary system commands.
static IException ProcessIsisMessageFromChild(QString code, QString msg)
This interprets a message sent along the pipe from a child process to us (the parent).
int keywords() const
Returns the number of keywords contained in the PvlContainer.
Contains multiple PvlContainers.
Definition PvlGroup.h:41
Container for cube-like labels.
Definition Pvl.h:119
PvlGroup & group(const int index)
Return the group at the specified index.
int groups() const
Returns the number of groups contained.
Definition PvlObject.h:75
int objects() const
Returns the number of objects.
Definition PvlObject.h:219
This is free and unencumbered software released into the public domain.
Definition Apollo.h:16
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
Definition IString.cpp:211
int toInt(const QString &string)
Global function to convert from a string to an integer.
Definition IString.cpp:93
Namespace for the standard library.