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