Isis 3 Programmer Reference
ProgramLauncher.cpp
1
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
22using namespace std;
23
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 QString command = program.expanded() + " " + parameters +
49 " -pid=" + toString(getpid());
50
51 if(!isIsisProgram) {
52 QString msg = "Program [" + programName + "] does not appear to be a "
53 "valid Isis program";
54 throw IException(IException::Unknown, msg, _FILEINFO_);
55 }
56
57 QString serverName = "isis_" + Application::UserName() +
58 "_" + toString(getpid());
59
60 QLocalServer server;
61 server.listen(serverName);
62
63 QProcess childProcess;
64 childProcess.setProcessChannelMode(QProcess::ForwardedChannels);
65 childProcess.start(command);
66 childProcess.waitForStarted();
67
68 bool connected = false;
69
70 while(!connected && childProcess.state() != QProcess::NotRunning) {
71 // Give time for the process to connect to us or for it to finish
72 // wait 30s for the new connection....
73 connected = server.waitForNewConnection(30000);
74 childProcess.waitForFinished(100);
75 }
76
77 if(!connected) {
78 QString msg = "Isis child process failed to communicate with parent";
79 throw IException(IException::Programmer, msg, _FILEINFO_);
80 }
81
82 QLocalSocket *childSocket = server.nextPendingConnection();
83 IException errors;
84
85 // Don't return until we're done running this program
86 while(childSocket->state() != QLocalSocket::UnconnectedState) {
87 bool insideCode = true;
88 bool messageDone = false;
89
90 QString code;
91 QString message;
92 QByteArray lineData;
93
94 if(childSocket->waitForReadyRead(1000)) {
95 lineData = childSocket->read(childSocket->bytesAvailable());
96
97 for(int i = 0; i < lineData.size(); i++) {
98 if(insideCode) {
99 if(lineData[i] != (char)27) {
100 code += lineData[i];
101 }
102 else {
103 insideCode = false;
104 }
105 }
106 else {
107 if(lineData[i] != (char)27) {
108 message += lineData[i];
109 }
110 else {
111 messageDone = true;
112 insideCode = true;
113 i ++; // skip \n that should always exist here
114 }
115 }
116
117 if(messageDone) {
118 errors.append(
119 ProcessIsisMessageFromChild(code, message));
120 code = "";
121 message = "";
122 messageDone = false;
123 }
124 }
125 }
126 }
127
128 childProcess.waitForFinished();
129
130 if(childProcess.exitCode() != 0) {
131 QString msg = "Running Isis program [" + programName + "] failed with "
132 "return status [" + toString(childProcess.exitCode()) + "]";
133 throw IException(errors, IException::Unknown, msg, _FILEINFO_);
134 }
135 }
136
137
150 IException errors;
151
152 if(code == "PROGRESSTEXT" && iApp) {
153 iApp->UpdateProgress(msg, true);
154 }
155 else if(code == "PROGRESS" && iApp) {
156 iApp->UpdateProgress(toInt(msg), true);
157 }
158 else if(code == "LOG" && iApp) {
159 stringstream msgStream;
160 msgStream << msg;
161 Pvl logPvl;
162 msgStream >> logPvl;
163
164 if(logPvl.groups() == 1 &&
165 logPvl.keywords() == 0 &&
166 logPvl.objects() == 0) {
167 iApp->Log(logPvl.group(0));
168 }
169 }
170 else if(code == "GUILOG" && iApp) {
171 iApp->GuiLog(msg);
172 }
173 else if(code == "ERROR") {
174 stringstream msgStream;
175 msgStream << msg;
176 Pvl errorPvl;
177 msgStream >> errorPvl;
178
179 for(int i = 0; i < errorPvl.groups(); i++) {
180 PvlGroup &g = errorPvl.group(i);
181 QString emsg = g["Message"];
182 int ecode = g["Code"];
183 QString efile = g["File"];
184 int eline = g["Line"];
185
186 errors.append(
187 IException((IException::ErrorType)ecode, emsg, efile.toLatin1().data(), eline));
188 }
189 }
190
191 return errors;
192 }
193
194
206 void ProgramLauncher::RunSystemCommand(QString fullCommand) {
207 int status = system(fullCommand.toLatin1().data());
208
209 if(status != 0) {
210 QString msg = "Executing command [" + fullCommand +
211 "] failed with return status [" + toString(status) + "]";
212 throw IException(IException::Programmer, msg, _FILEINFO_);
213 }
214 }
215} //end namespace isis
static void Log(PvlGroup &results)
Writes Pvl results to sessionlog and printfile.
static void GuiLog(const Pvl &results)
Writes the Pvl results to the sessionlog, but not to the printfile.
void UpdateProgress(const QString &text, bool print)
Updates the progress bar in the gui.
static QString UserName()
Returns the user name.
File name manipulation and expansion.
Definition FileName.h:100
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).
Contains multiple PvlContainers.
Definition PvlGroup.h:41
Container for cube-like labels.
Definition Pvl.h:119
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.